本書從文字翻譯的案例切入,假設把英文翻譯為法文,每個英文單詞為關鍵字,其對應法文為衛星資料。用二叉尋找樹儲存,該怎麼設計這個尋找樹。即使是紅/黑樹狀結構,尋找的時間複雜度也為O(lgn)即樹的深度。但是因為文章中某個單詞出現的頻率不同,所以可能有些頻率很高的單詞比如the的深度可能很深,而不常見的Aha的深度卻可能很淺。根據直覺,我們應該讓本例中the更加靠近樹根才對(其實即使機率最高也不見得就是樹根)。我們應該讓尋找整個樹的期望次數最小,即構建一個最優二叉尋找樹。一個最優二叉尋找樹的左右子樹的肯定也是最優的。數組p中是k1~k5的機率。k1到k5是從小到大的順序,即字典序。當找不到要尋找到英文單詞時肯定最終會走到樹葉,每個樹葉出現的機率儲存到數組q中。我一直沒弄明白這個樹葉的機率作者是怎麼搞出來的。誰知道告訴我一下。
程式一個注意的地方就是浮點數比較,不能直接比較,除非相差很大才行,如果兩個浮點數相等,要是直接使用大於符號進行判斷也有可能成立。
代碼如下:
#include <iostream>using namespace std;void OpticalBST(double *p,double *q,int n,double (*e)[6],int (*root)[6]){double w[n+1][6];for(int i=1;i<=n+1;i++){e[i][i-1]=q[i-1];w[i][i-1]=q[i-1]; }for(int l=1;l<=n;l++){for(int i=1;i<=n-l+1;i++){int j=i+l-1;e[i][j]=1<<30;//cout<<e[i][j];system("pause");w[i][j]=w[i][j-1]+p[j]+q[j];//子樹i...j的總機率 for(int r=i;r<=j;r++){double t=e[i][r-1]+e[r+1][j]+w[i][j];if(e[i][j]-t>0.0000000001)//不能直接用e[i][j]>t,因為如果e[i][j]和t都是浮點數,即使相等的話,相減可能也不等於0 {e[i][j]=t;root[i][j]=r;} }}}}void ConstructOpticalBST(int (*root)[6],int i,int j){if(i==1&&j==5){cout<<"k"<<root[i][j]<<"是根"<<endl;//system("pause");}if(i<root[i][j]) {cout<<"k"<<root[i][root[i][j]-1]<<"是k"<<root[i][j]<<"的左孩子"<<endl;ConstructOpticalBST(root,i,root[i][j]-1);}else{cout<<"d"<<root[i][j]-1<<"是k"<<root[i][j]<<"的左孩子"<<endl;}if(root[i][j]<j){cout<<"k"<<root[root[i][j]+1][j]<<"是k"<<root[i][j]<<"的右孩子"<<endl;ConstructOpticalBST(root,root[i][j]+1,j);}else{cout<<"d"<<root[i][j]<<"是k"<<root[i][j]<<"的右孩子"<<endl;} }int main(){int n=5;double p[6]={0,0.15,0.1,0.05,0.1,0.2};//第一個不用。1~5分別代表k1~k5,並且k1~k5是按從下到大順序排列。K的順序對於輸出整個數很重要。 double q[6]={0.05,0.1,0.05,0.05,0.05,0.1}; double e[7][6];int root[6][6];OpticalBST(p,q,n,e,root);ConstructOpticalBST(root,1,5); system("pause"); return 0;}