最优二叉查找树_动态规划

Posted henuliulei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最优二叉查找树_动态规划相关的知识,希望对你有一定的参考价值。

 

原问题是给出各个节点和各个节点的被查找概率,然后构造一棵各个节点平均被查找比较次数最小的树,则该问题可以用动态规划来解决

技术分享图片

示例如下

技术分享图片

推广到一般的情况,并设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求出,等我有空再把代码补上,用程序把树的构造描绘出来

以上是关于最优二叉查找树_动态规划的主要内容,如果未能解决你的问题,请参考以下文章

动态规划习题之最优二叉搜索树

动态规划之最优二叉查找树

动态规划之最优二叉查找树

动态规划之最优二叉查找树

c_cpp 【动态规划】最优二叉搜索树问题【3.11】

最优二叉搜索树