次優查詢樹的建立

2021-09-23 21:00:19 字數 3680 閱讀 3838

查詢效率最高即平均查詢長度最小,根據前面所學知識,我們可以給出有序表在非等概率情況下應遵循的兩個原則:   

1、最先訪問的結點應是訪問概率最大的結點; 

2、每次訪問應使結點兩邊尚未訪問的結點的被訪概率之和盡可能相等。

這兩個原則可用一句話來表示,即判定樹為帶權內路徑長度之和最小的二叉樹,亦即:ph = ∑wihi  最小,其中 n 為有序表長度,hi 為第 i 個結點在判定樹上的層次數,wi = cpi,c 為某個常數,pi 為第 i 個結點的查詢概率。

這樣的樹稱為靜態最優查詢樹(static optimal search tree),構造這樣一棵樹的時間代價太大,亦即時間複雜度很大,因此我們通常是構造次優查詢樹(nearly optimal search tree),構造它的時間代價遠遠低於構造最優查詢樹,但查詢效能只比最優查詢樹差1%~2%,很少差3%以上。

次優查詢樹的構造: 

設有序表每個記錄的權值為 wl,wl+1,…,wh,第乙個應訪問的結點號為 i ,則有: 

δpi =   ∑wj - ∑wj   最小,即 δpi = min  

再分別對 和 分別構造次優查詢樹。 

為便於計算,引入累計權值swi=∑wj,並設wl-1=swl-1=0,則:

由於在構造次優查詢樹時沒有考慮前面說的原則一,因此被選為根的結點的權值可能比其鄰近結點的權值小,此時應對查詢樹作適當的調整,將相鄰權值大的結點作為根結點。

次優查詢樹的查詢方法與折半查詢類似,其平均查詢長度與 log n 成正比。

注意:利用上述演算法構造好次優二叉樹之後,可能並不是最優的,因為在構造過程中,沒有考慮單個關鍵字的相應權值,則有可能出現被選為根的關鍵字的權值比與

它相鄰的關鍵字的權值小。此時應做適當的調整:選取鄰近的權值較大的關鍵字作為次優查詢樹的根節點(也就是左旋和右旋子樹

#include#include#include#include#include#include#define n 100

#define maxn 0x3f3f3f3f

using namespace std;

templateclass treenode

};templateclass nearlyoptimalsearchtree;

templatevoid nearlyoptimalsearchtree::input()

templatevoid nearlyoptimalsearchtree::init()

}t = new treenode;

t->val = val[i];

t->w = w[i];

if(ld==rd) return;

buildt(ld, i-1, t->child[0]);

buildt(i+1, rd, t->child[1]);

}templatevoid nearlyoptimalsearchtree::adjustment(treenode* &t) else

}adjustment(t->child[0]);

adjustment(t->child[1]);

}templatevoid nearlyoptimalsearchtree::rotatet(treenode* &o, int x)

templatevoid nearlyoptimalsearchtree::outt(treenode* t)

int main()

/*  演示結果如下:

a 1b 1

c 2d 5

e 3f 4

g 4h 3

i 5沒有調整前的先序遍歷:

f d b a c e g h i

調整後的先序遍歷:

d c b a f e g i h

a 1b 30

c 2d 29

e 2沒有調整前的先序遍歷:

c b a d e

調整後的先序遍歷:

b a d c e

*/

#include#include#include#include#include#include#include#include#define n 100

#define maxn 0x3f3f3f3f

using namespace std;

templateclass treenode

};templateclass nearlyoptimalsearchtree;

templatevoid nearlyoptimalsearchtree::input()

templatevoid nearlyoptimalsearchtree::init()

}t = new treenode;

t->val = val[i];

t->w = w[i];

if(ld==rd) return;

buildt(ld, i-1, t->child[0]);

buildt(i+1, rd, t->child[1]);

}templatevoid nearlyoptimalsearchtree::adjustment(treenode* &t) else

}adjustment(t->child[0]);

adjustment(t->child[1]);

}templatevoid nearlyoptimalsearchtree::rotatet(treenode* &o, int x)

templatevoid nearlyoptimalsearchtree::widtht(treenode* t)

templatevoid nearlyoptimalsearchtree::outt(treenode* t) else

}//放入孩子節點

if(tt->child[0]) q.push(tt->child[0]), ++nn;

if(tt->child[1]) q.push(tt->child[1]), ++nn;

++i;

if(i>n) else

first = false;

if(qq.empty())

}printf("\n");

if(q.empty()) break;//這是最後一層

cout

nost.input();

nost.init();

return 0;}/*

//演示結果

a 1b 1

c 2d 5

e 3f 4

g 4h 3

i 5沒有調整前的先序遍歷:

f -------

| |d g

-------------

| | |

b e h

-----------------

| | |

a c i

調整後的先序遍歷:

d -------

| |

c f

-----------

| | |

b e g

-----------------

| |

a i

------------------|h

*/

次優查詢樹的建立

查詢效率最高即平均查詢長度最小,根據前面所學知識,我們可以給出有序表在非等概率情況下應遵循的兩個原則 1 最先訪問的結點應是訪問概率最大的結點 2 每次訪問應使結點兩邊尚未訪問的結點的被訪概率之和盡可能相等。這兩個原則可用一句話來表示,即判定樹為帶權內路徑長度之和最小的二叉樹,亦即 ph wihi ...

構造次優查詢樹

似乎有些錯誤,但是錯在哪了呢?include include using namespace std const int num 9 int value num float weight num float sum weight num void init sum weight struct tre...

靜態樹表查詢演算法 次優查詢樹

自 有關在靜態查詢表中對特定關鍵字進行順序查詢 折半查詢或者分塊查詢,都是在查詢表中各關鍵字被查詢概率相同的前提下進行的。例如查詢表中有 n 個關鍵字,表中每個關鍵字被查詢的概率都是 1 n。在等概率的情況,使用折半查詢演算法的效能最優。而在某些情況下,查詢表中各關鍵字被查詢的概率是不同的。例如水果...