原问题是给出各个节点和各个节点的被查找几率,而后构造一棵各个节点平均被查找比较次数最小的树,则该问题能够用动态规划来解决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