動態規劃之最優二叉搜尋樹

2021-07-29 13:40:31 字數 2152 閱讀 2101

最優二叉搜尋樹簡介

舉例以及詳細分析

**塊測試結果

1、概念引入

基於統計先驗知識,我們可統計出乙個數表(集合)中各元素的查詢概率,理解為集合各元素的出現頻率。比如中文輸入法字型檔中各詞條(單字、片語等)的先驗概率,針對使用者習慣可以自動調整詞頻——所謂動態調頻、高頻先現原則,以減少使用者翻查次數。這就是最優二叉查詢樹問題:查詢過程中鍵值比較次數最少,或者說希望用最少的鍵值比較次數找到每個關鍵碼(鍵值)。為解決這樣的問題,顯然需要對集合的每個元素賦予乙個特殊屬性——查詢概率。這樣我們就需要構造一顆最優二叉查詢樹。

2、最優二叉搜尋樹

最優二叉查詢樹:

給定n個互異的關鍵字組成的序列k=(k1,k2,…,kn),且關鍵字有序(k1小於k2小於…小於kn),我們想從這些關鍵字中構造一棵二叉查詢樹。對每個關鍵字ki,一次搜尋搜尋到的概率為pi。可能有一些搜尋的值不在k內,因此還有n+1個「虛擬鍵」d0,d1,…,dn,他們代表不在k內的值。具體:d0代表所有小於k1的值,dn代表所有大於kn的值。而對於i = 1,2,…,n-1,虛擬鍵di代表所有位於ki和ki+1之間的值。對於每個虛擬鍵,一次搜尋對應於di的概率為qi。要使得查詢乙個節點的期望代價(代價可以定義為:比如從根節點到目標節點的路徑上節點數目)最小,就需要建立一棵最優二叉查詢樹。

圖一顯示了給定上面的概率分布pi、qi,生成的兩個二叉查詢樹的例子。圖二就是在這種情況下一棵最優二叉查詢樹。

動態規劃法策略是將問題分成多個階段,逐段推進計算,後繼例項解由其直接前趨例項解計算得到。對於最優bst問題,利用減一技術和最優性原則,如果前n-1個節點構成最優bst,加入乙個節點an 後要求構成規模n的最優bst。按 n-1, n-2 , … , 2, 1 遞迴,問題可解。自底向上計算:c[1, 2]→c[1, 3] →… →c[1, n]。為不失一般性用

c[i, j] 表示由構成的bst的耗費。其中1≤i ≤j ≤n。這棵樹表示為tij。從中選擇乙個鍵ak作根節點,它的左子樹為tik-1,右子樹為tk+1j。要求選擇的k 使得整棵樹的平均查詢次數c[i, j]最小。左右子樹遞迴執行此過程。(根的生成過程)

遞推計算式如下:

基本演算法:

for (d = 1; d <= num - 1; d++)//d是[i,j]之間的距離

}r[i][j] = kmin;//記錄最優根

sum = p[i];

for (s = i + 1; s <= j; s++)

c[i][j] = temp + sum;}}

}void dptimalbstprint(int first, int last, int **r)

}int main(void)

float **c = (float **)malloc(sizeof(float *)*(num + 2));

for (i = 0; i < num + 2; i++)

int **r = (int **)malloc(sizeof(int *)*(num + 2));

for (i = 0; i < num + 2; i++)

dptimalbst(num, p, c, r);

printf("該最有二叉搜尋樹的期望代價為:%f\n", c[1][num]);

printf("構成的最優二叉查詢樹的中序遍歷結果為:");

動態規劃之最優二叉搜尋樹

在看這張之前,最好看看我寫的 動態規劃詳解 裡面都是講理論基礎,我下面的分析都是在此基礎上進展的。給定乙個由n個互異的關鍵字組成的序列k k1,k2,kn 且關鍵字有序 因此有k1 k2 kn 從這些關鍵字中構造一棵二叉查詢樹。對每個關鍵字ki,一次搜尋為ki的概率是pi。某些搜尋的值可能不在k內,...

動態規劃之最優二叉搜尋樹

最優二叉搜尋樹 public class optimalbst k1.k5的概率 private double q d1.d5的概率 public static void main string args public optimalbst 計算得到最優二叉搜尋樹期望代價 private void ...

動態規劃之最優二叉搜尋樹(演算法導論)

1 一些概念 二叉搜尋樹 在二叉樹中,對任意的節點x其左子樹的所有節點都不大於x.key,其右子樹的所有節點都不小於x.key。滿足此條件的二叉樹稱為二叉搜尋樹。對二叉搜尋樹進行中序遍歷將會得到乙個單調遞增的數列。最優二叉樹 在二叉樹中,不同的節點都有不同的訪問頻率。為了減少查詢某個節點所需要遍歷的...