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

2022-03-16 11:18:32 字數 3325 閱讀 3086

**自:

有關在靜態查詢表中對特定關鍵字進行順序查詢、折半查詢或者分塊查詢,都是在查詢表中各關鍵字被查詢概率相同的前提下進行的。

例如查詢表中有 n 個關鍵字,表中每個關鍵字被查詢的概率都是 1/n。在等概率的情況,使用折半查詢演算法的效能最優。

而在某些情況下,查詢表中各關鍵字被查詢的概率是不同的。例如水果商店中有很多種水果,對於不同的顧客來說,由於口味不同,各種水果可能被選擇的概率是不同的。假設該顧客喜吃酸,那麼相對於蘋果和橘子,選擇橘子的概率肯定要更高一些。

在查詢表中各關鍵字查詢概率不相同的情況下,對於使用折半查詢演算法,按照之前的方式進行,其查詢的效率並不一定是最優的。例如,某查詢表中有 5 個關鍵字,各關鍵字被查詢到的概率分別為:0.1,0.2,0.1,0.4,0.2(全部關鍵字被查詢概率和為 1 ),則根據之前介紹的折半查詢演算法,建立相應的判定樹為(樹中各關鍵字用概率表示):

圖 1 折半查詢對應的判定樹

折半查詢查詢成功時的平均查詢長度的計算方式為:

asl = 判定樹中各結點的查詢概率*所在層次

所以該平均查詢長度為:

asl=0.1*1 + 0.1*2 + 0.4*2 + 0.2*3 + 0.2*3 = 2.3
由於各關鍵字被查詢的概率是不相同的,所以若在查詢時遵循被查詢關鍵字先和查詢概率大的關鍵字進行比對,建立的判定樹為:

圖 2 折半查詢對應的新判定樹

相應的平均查詢長度為:

asl=0.4*1 + 0.2*2 + 0.2*2 + 0.1*3 + 0.1*3=1.8
後者折半查詢的效率要比前者高,所以在查詢表中各關鍵字查詢概率不同時,要考慮建立一棵查詢效能最佳的判定樹。若在只考慮查詢成功的情況下,描述查詢過程的判定樹其帶權路徑長度之和(用 ph 表示)最小時,查詢效能最優,稱該二叉樹為靜態最優查詢樹。

帶權路徑之和的計算公式為:ph = 所有結點所在的層次數 * 每個結點對應的概率值。

但是由於構造最優查詢樹花費的時間代價較高,而且有一種構造方式建立的判定樹的查詢效能同最優查詢樹僅差 1% - 2%,稱這種極度接近於最優查詢樹的二叉樹為次優查詢樹

首先取出查詢表中每個關鍵字及其對應的權值,採用如下公式計算出每個關鍵字對應的乙個值:

其中 wj 表示每個關鍵字的權值(被查詢到的概率),h 表示關鍵字的個數。

表中有多少關鍵字,就會有多少個 △pi ,取其中最小的做為次優查詢樹的根結點,然後將表中關鍵字從第 i 個關鍵字的位置分成兩部分,分別作為該根結點的左子樹和右子樹。同理,左子樹和右子樹也這麼處理,直到最後構成次優查詢樹完成。

**實現為:

typedef

int keytype;

// 定義關鍵字型別

typedef

struct

elemtype;

// 定義元素型別

typedef

struct bitnode

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)

}

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 的值,找出整棵查詢表的根結點:

通過重新分別計算左右兩查詢子表的 △p 的值,得知左子樹的根結點為 d,右子樹的根結點為 h (如上圖右側所示),以兩結點為分界線,繼續判斷兩根結點的左右子樹:

通過計算,構建的次優查詢樹如上圖右側二叉樹所示。

後邊還有一步,判斷關鍵字 a 和 c 在樹中的位置,最後一步兩個關鍵字的權值為 0 ,分別作為結點 b 的左孩子和右孩子,這裡不再用圖表示。

注意:在建立次優查詢樹的過程中,由於只根據的各關鍵字的 p

的值進行構建,沒有考慮單個關鍵字的相應權值的大小,有時會出現根結點的權值比孩子結點的權值還小,此時就需要適當調整兩者的位置。

總結

由於使用次優查詢樹和最優查詢樹的效能差距很小,構造次優查詢樹的演算法的時間複雜度為 o(nlogn),因此可以使用次優查詢樹表示概率不等的查詢表對應的靜態查詢表(又稱為靜態樹表)。

靜態最優查詢與次優查詢樹

問題描述 給出n nn個元素的權值w i w i w i 問如何構造查詢樹使得查詢效率最高?靜態最優查詢樹 將n個元素的權值有序排列,設定opt imal i,j optimal i,j optima l i,j 表示區間 i,j i,j i,j 之間的元素構造的最小ph值的子樹。易知有關係 o p...

構造次優查詢樹的演算法

根據書上的例子寫出的演算法 儲存待查詢的內容的結構體元素 typedef struct elemkey stru elemkey 求元素low到元素high的權值和 int sumkey elemkey elemkey,int low,int high return sum 構造次優查詢樹 void...

構造次優查詢樹

似乎有些錯誤,但是錯在哪了呢?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...