码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-12-06 01:26:45      阅读:233      评论:0      收藏:0      [点我收藏+]

标签:class   输入   int   turn   范围   bubuko   示例   概率   程序   

 

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

技术分享图片

示例如下

技术分享图片

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

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

标签:class   输入   int   turn   范围   bubuko   示例   概率   程序   

原文地址:https://www.cnblogs.com/henuliulei/p/10074216.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!