最優二叉查找樹_動態規划


 

原問題是給出各個節點和各個節點的被查找概率,然后構造一棵各個節點平均被查找比較次數最小的樹,則該問題可以用動態規划來解決

示例如下

推廣到一般的情況,並設T(i, j)是由記錄{ri, …, rj}(1≤i≤j≤n)構成的二叉查找樹,C(i, j)是這棵二叉查找樹的平均比較次數,有下列分析

觀察這個表,可知可知左邊的表的第一行的第四列就是我們要求的最優平均比較次數,而右邊的表我們可以知道在c(i ,j)得到最優解,即平均查找次數最小的根節點,比如一共四個節點,則我們從右邊的R(1,4)的值即3是這四個節點構成的樹的根節點。則樹的左子樹變為c(1,2),他的根節點是r(1,2)=2,然后2又有左節點1,而4則是3的根節點。則樹的樣子便出來了。

代碼如下

 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 }

運行結果如下

具體樹的構造我們可以從數組r求出,等我有空再把代碼補上,用程序把樹的構造描繪出來


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM