原問題是給出各個節點和各個節點的被查找機率,而後構造一棵各個節點平均被查找比較次數最小的樹,則該問題能夠用動態規劃來解決c++
示例以下數組
推廣到通常的狀況,並設T(i, j)是由記錄{ri, …, rj}(1≤i≤j≤n)構成的二叉查找樹,C(i, j)是這棵二叉查找樹的平均比較次數,有下列分析spa
觀察這個表,可知可知左邊的表的第一行的第四列就是咱們要求的最優平均比較次數,而右邊的表咱們能夠知道在c(i ,j)獲得最優解,即平均查找次數最小的根節點,好比一共四個節點,則咱們從右邊的R(1,4)的值即3是這四個節點構成的樹的根節點。則樹的左子樹變爲c(1,2),他的根節點是r(1,2)=2,而後2又有左節點1,而4則是3的根節點。則樹的樣子便出來了。code
代碼以下blog
1 #include<bits/stdc++.h> 2 using namespace std; 3 double BST(int n,double p[],double c[][100],int r[][100]) 4 { 5 for(int i=1;i<=n;i++){//按式1和式2初始化 6 c[i][i-1]=0; 7 c[i][i]=p[i]; 8 r[i][i]=i; 9 } 10 c[n+1][n]=0; 11 for(int d=1;d<n;d++){//安對角線計算,此時是n-1個對角線 12 for(int i=1;i<=n-d;i++){//行的取值範圍 13 int j=i+d;//求出在對角線上的i對應的j 14 double minnum=99999.0;//出是一個較大的值 15 int mink=i; 16 double sum=0; 17 for(int k=i;k<=j;k++) 18 { 19 sum=sum+p[k]; 20 if(c[i][k-1]+c[k+1][j]<minnum){//不斷比較,獲取最小的值 21 minnum=c[i][k-1]+c[k+1][j]; 22 mink=k; 23 } 24 } 25 c[i][j]=minnum+sum;//獲得了最小值 26 r[i][j]=mink;//記錄取得最小值時的根節點 27 } 28 29 } 30 return c[1][n]; 31 } 32 int main() 33 { 34 cout << "請輸入樹的節點的個數" << endl; 35 int n; 36 cin >> n; 37 cout << "請輸入每一個節點的被查找機率" << endl; 38 double p[n]; 39 memset(p,0,sizeof(p)); 40 for(int i=1;i<=n;i++) 41 { 42 cin >> p[i]; 43 } 44 double c[n+2][100]; 45 int r[n+2][100]; 46 memset(r,0,sizeof(r)); 47 memset(c,0,sizeof(c)); 48 double s=BST(n,p,c,r); 49 cout << "最小平均比較次數爲" << s<<endl; 50 cout << "平均最小几率矩陣以下:" << endl; 51 for(int i=1;i<=n+1;i++){ 52 for(int j=0;j<=n;j++){ 53 cout << c[i][j] << " "; 54 } 55 cout << endl; 56 } 57 58 cout << "最優二叉查找樹對應的根節點 " << endl; 59 for(int i=1;i<=n+1;i++){ 60 for(int j=0;j<=n;j++){ 61 cout << r[i][j] << " "; 62 } 63 cout << endl; 64 } 65 66 return 0; 67 }
運行結果以下ci
具體樹的構造咱們能夠從數組r求出,等我有空再把代碼補上,用程序把樹的構造描繪出來it