原理
首先取出查找表中每個關鍵字及其對應的權值,采用如下公式計算出每個關鍵字對應的一個值:
其中 wj 表示每個關鍵字的權值(被查找到的概率),h 表示關鍵字的個數。
表中有多少關鍵字,就會有多少個 △Pi ,取其中最小的做為次優查找樹的根結點,然后將表中關鍵字從第 i 個關鍵字的位置分成兩部分,分別作為該根結點的左子樹和右子樹。同理,左子樹和右子樹也這么處理,直到最后構成次優查找樹完成。
typedef int KeyType;//定義關鍵字類型
typedef struct{
KeyType key;
}ElemType;//定義元素類型
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
//定義變量
int i;
int min;
int dw;
//創建次優查找樹,R數組為查找表,sw數組為存儲的各關鍵字的概率(權值),low和high表示的sw數組中的權值的范圍
void SecondOptimal(BiTree T, ElemType R[], float sw[], int low, int high){
//由有序表R[low...high]及其累計權值表sw(其中sw[0]==0)遞歸構造次優查找樹
i = low;
min = abs(sw[high] - sw[low]);
dw = sw[high] + sw[low - 1];
//選擇最小的△Pi值
for (int j = low+1; j <=high; j++){
if (abs(dw-sw[j]-sw[j-1])<min){
i = j;
min = abs(dw - sw[j] - sw[j - 1]);
}
}
T = (BiTree)malloc(sizeof(BiTNode));
T->data = R[i];//生成結點(第一次生成根)
if (i == low) T->lchild = NULL;//左子樹空
else SecondOptimal(T->lchild, R, sw, low, i - 1);//構造左子樹
if (i == high) T->rchild = NULL;//右子樹空
else SecondOptimal(T->rchild, R, sw, i + 1, high);//構造右子樹
}
完整事例演示
例如,一含有 9 個關鍵字的查找表及其相應權值如下表所示:
則構建次優查找樹的過程如下:首先求出查找表中所有的 △P 的值,找出整棵查找表的根結點:
例如,關鍵字 F 的 △P 的計算方式為:從 G 到 I 的權值和 - 從 A 到 E 的權值和 = 4+3+5-1-1-2-5-3 = 0。
通過上圖左側表格得知,根結點為 F,以 F 為分界線,左側子表為 F 結點的左子樹,右側子表為 F 結點的右子樹(如上圖右側所示),繼續查找左右子樹的根結點:
通過重新分別計算左右兩查找子表的 △P 的值,得知左子樹的根結點為 D,右子樹的根結點為 H (如上圖右側所示),以兩結點為分界線,繼續判斷兩根結點的左右子樹:
通過計算,構建的次優查找樹如上圖右側二叉樹所示。后邊還有一步,判斷關鍵字 A 和 C 在樹中的位置,最后一步兩個關鍵字的權值為 0 ,分別作為結點 B 的左孩子和右孩子,這里不再用圖表示。
注意:在建立次優查找樹的過程中,由於只根據的各關鍵字的 P 的值進行構建,沒有考慮單個關鍵字的相應權值的大小,有時會出現根結點的權值比孩子結點的權值還小,此時就需要適當調整兩者的位置。
歡迎瀏覽我的主頁