演算法導論 動態規劃之最優二叉查詢樹

2021-06-19 09:50:46 字數 1811 閱讀 3898

如果我們想寫乙個單詞查詢的軟體的話,我們的目的就是讓查詢的總時間最短,我們首先想到用之前的二叉查詢樹。我們可以用紅黑樹或者其它的平衡二叉樹來保證每個單詞的搜尋時間。但是每個單詞出現的頻率一般不同,因此我們希望把頻率較大的單詞放在離根比較近的地方,頻率較小的放在離葉子較近的地方。而且,我們所要查詢的單詞詞庫中沒有,這也值得考慮。

由上文可知,ki表示單詞,di表示不能查到的情況。由上面的例子可知,一棵最優二叉樹不一定是高度最小的樹。我們也不一定總把頻率最大的放在根部。

和矩陣鏈乘法一樣,窮舉所有的可能行肯定不是乙個好的演算法。由於具有動態規劃的特徵,毫無疑問,我們將使用動態規劃法。

對於原序列,我們假設第k個元素(採用遍歷的方法)作為根時可以得到最優解,由於是二叉查詢樹,則前k-1個元素在左子樹,剩餘元素在右子樹。接下來,我們要分別在左、右子樹中找到最優二叉樹,於是我們可以用相同的方法:假設左、右子樹中第m,n個為根時,可以得到最優解,依此類推,就可以求得整體最優解。上面的解法中,可能存在左或者右子樹為空的情況:

通過推導,可以遞推公式:

其中e表示搜尋的代價,q[i]為d[i]的出現頻率,w為子樹總的概率。

具體程式實現如下:

#include#define n 7

void optimal_bst(float *p,float *q,int n,float e[n],int root[n]);

void main()

;//關鍵字出現的概率

float q=;//搜尋不到關鍵字的幾種情況的概率

int n=6;//關鍵字個數

float e[n][n]=;//儲存搜尋的代價

int root[n][n]=;//子樹的根,便於重構最優二叉樹

optimal_bst(p,q,n,e,root);

for(int i=1;i<6;i++)

for(int j=5;j>=i;j--)

printf("從第%d個元素到第%d個元素的最優二叉查詢樹的頂點為:%d\n",i,j,root[i][j]);

}void optimal_bst(float *p,float *q,int n,float e[n],int root[n])

; float t=0;

for(int i=1;i<=n;i++)//左右子樹為空的情況

for(int l=1;l<=n;l++)

for(int i=1;i<=n-l+1;i++)

{ int j=0;

j=i+l-1;

e[i][j]=10000;//初始化為很大的值,可以隨意設定

w[i][j]=w[i][j-1]+p[j]+q[j];//

for(int r=i;r<=j;r++)//r代表以下標r為根,r在所有的子樹節點中遍歷

上述程式的執行時間為o(n^3),這和前面的矩陣鏈乘法是一樣的。

原文:

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

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

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

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

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

最優二叉搜尋樹簡介 舉例以及詳細分析 塊測試結果 1 概念引入 基於統計先驗知識,我們可統計出乙個數表 集合 中各元素的查詢概率,理解為集合各元素的出現頻率。比如中文輸入法字型檔中各詞條 單字 片語等 的先驗概率,針對使用者習慣可以自動調整詞頻 所謂動態調頻 高頻先現原則,以減少使用者翻查次數。這就...