问题描述:

 维基百科定义:

https://en.wikipedia.org/wiki/Optimal_binary_search_tree

 In the static optimality problem as defined by Knuth we are given a set of n{\displaystyle n} ordered elements and a set of 2n+1{\displaystyle 2n+1} probabilities. We will denote the elements a1{\displaystyle a_{1}} through an{\displaystyle a_{n}} and the probabilities A1{\displaystyle A_{1}} through An{\displaystyle A_{n}} and B0B_{0} through Bn B_{n}. Ai A_{i} is the probability of a search being done for element aia_{i}. For 1≤i<n 1\leq i, define the probability of bib_i is BiB_{i} is the probability of a search being done for an element between aia_{i} and ai+1 a_{i+1} , B0B_{0} is the probability of a search being done for an element strictly less than a0a_{0}, and BnB_{n} is the probability of a search being done for an element strictly greater than ana_{n}. These 2n+1 2n+1 probabilities cover all possible searches, and therefore add up to one.
 (∑ni=1Ai+∑ni=0Bi=1\sum_{i=1}^nA_i+\sum_{i=0}^nB_i = 1)
The static optimality problem is the optimization problem of finding the binary search tree that minimizes the expected search time, given the 2n+12n+1 probabilities. As the number of possible trees on a set of nn elements is (2nn)1n+1(2nn)1n+1{\displaystyle {2n \choose n}{\frac {1}{n+1}}} {2n \choose n}\frac{1}{n+1}, which is exponential in nn, brute-force search is not usually a feasible solution.

需要说明的是静态的最优二叉搜索树不一定是高度最矮的二叉搜索树。

O(n3)O(n^3)的动态规划算法:

期望搜索代价
E[T]=∑ni=1(depth(ai)+1)∗Ai+∑ni=0(depth(bi)+1)∗BiE[T] = \sum_{i=1}^n(depth(a_i)+1)*Ai+\sum_{i=0}^n(depth(b_i)+1)*B_i
=1+∑ni=1depth(ai)∗Ai+∑ni=0depth(bi)∗Bi = 1+\sum_{i=1}^ndepth(a_i)*A_i+\sum_{i=0}^ndepth(b_i)*B_i
最优子结构
观察一颗最优二叉搜索树的子树T′T'必然包含连续的节点<ai<ai+1<...<aj><script type="math/tex" id="MathJax-Element-30"><...</script>而且我们用“剪贴法”证明 T′T' 必定是包含节点<ai,ai+1,...,aj><script type="math/tex" id="MathJax-Element-32"></script>
的一颗最优二叉搜索树,如果说T′T' 不是包含节点ai,...,aja_i,...,a_j 的 Optimal BST,则我们可以将用包含ai,...,aja_i, ...,a_j 的另外一颗Optimal BST T′′T'' 将其替换掉。
子问题的递归描述
定义eije_{ij} 为包含节点 <ai,...,aj>(n≥j≥i−1)<script type="math/tex" id="MathJax-Element-38">(n \geq j\geq i-1)</script> 的一颗最优二叉搜索树的期望搜索代价

当一颗子树成为一个节点的子树时,由于每个节点的深度增加了一,因此增加的期望搜索代价为
wi,j=∑jm=iAm+∑jn=iBiw_{i,j} = \sum_{m=i}^jA_m+\sum_{n=i}^jB_i
ei,je_{i,j} 的递归公式为
ei,j=Ar+(ei,r−1+wi,r−1)+(er+1,j+wr+1,j)e_{i,j} = A_r+(e_{i,r-1}+w_{i,r-1}) + (e_{r+1,j} + w_{r+1,j})

wi,j=Ar+wi,r−1+wr+1,jw_{i,j} = A_r +w_{i,r-1}+w_{r+1,j}
所以
ei,j=ei,r−1+er+1,j+wi,je_{i,j} = e_{i,r-1} + e_{r+1,j} +w_{i,j}
ei,je_{i,j} 的递归公式
>

ei,j={Bi−1,ei,j=ei,r−1+er+1,j+wi,j,if j=i−1if j≥i

e_{i,j}= \begin{cases} B_{i-1}, & \text {if $j = i-1$} \\ e_{i,j} = e_{i,r-1} + e_{r+1,j} +w_{i,j}, & \text{if $j \geq i$} \end{cases}
而 wi,j=wi,j−1+Aj+Bjw_{i,j} = w_{i,j-1}+A_j +B_j
编程实现
下面给出一个接收 <q1,...,qn><script type="math/tex" id="MathJax-Element-47"></script> 及<p0,...,pn><script type="math/tex" id="MathJax-Element-48"></script> 作为节点a1,...,ana_1,...,a_n 与b0,...bnb_0,...b_n 的概率作为输入返回期望ee及rootroot子树树根的代码

#include<cstdio>
#include<cfloat>
#include<iostream> #define INF DBL_MAX
#define maxn 100using namespace std;double e[maxn][maxn];int root[maxn][maxn];
void optimal_BST(double p[],double q[],int n)//p[1,n],q[0,n ]
{double w[n+2][n+2];for(int i=1 ; i<=n+1 ; i++){e[i][i-1] = q[i-1];w[i][i-1] = q[i-1];}for(int l =1 ; l<=n ; l++){for(int i= 1 ; i<=n-l+1 ; ++i){int j = i+l-1;e[i][j] = INF;w[i][j] = w[i][j-1] +p[j]+q[j];for(int r = i;r<=j ; r++){double t = e[i][r-1]+e[r+1][j]+w[i][j];if(t<e[i][j]){e[i][j] = t;root[i][j] = r;}}}}} 

递归输出子树

void print(int i,int j,int p)// 输出最优二叉树 {if(i-j==1){if(j<p)printf("b%d是a%d的左孩子\n",j,p);else printf("b%d是a%d的右孩子\n",j,p);return;}if(p==0){p = root[i][j];printf("a%d是根\n",p);print(i,p-1,p);print(p+1,j,p);}else if(root[i][j] <p){printf("a%d是a%d的左孩子\n",root[i][j],p);p = root[i][j];print(i,p-1,p);print(p+1,j,p); }else{printf("a%d是a%d的右孩子\n",root[i][j],p);p = root[i][j];print(i,p-1,p);print(p+1,j,p);}}

测试

int main(){//cout<<DBL_MAX<<endl;double A[] = {0,0.15,0.10,0.05,0.10,0.20};double B[] = {0.05,0.10,0.05,0.05,0.05,0.10};int n = sizeof(A)/sizeof(A[0])-1;optimal_BST( A,B,n);print( 1,n,0);printf("root:\n");for(int i=1 ; i<=n ; ++i){for(int j=1 ; j<=n ; ++j)printf("%d \t",root[i][j]);printf("\n");}return 0;}

运行结果

对应数据及最优二叉搜索树图

ii 0 1 2 3 4 5
AiA_{i} 0.15 0.10 0.05 0.10 0.20
BiB_{i} 0.05 0.10 0.05 0.05 0.05 0.10

最优二叉搜索树(Optimal BST)-算法导论相关推荐

  1. 动态规划最优二叉搜索树C语言,算法 – 动态规划:最优二叉搜索树

    好吧,我希望有人可以向我解释一下.我正在攻读决赛,我无法解决问题. 问题是动态编程;构造最优二叉搜索树(OBST).我理解一般的动态编程和特别是这个问题的概念,但我不明白这个问题的递归形式. 我得到的 ...

  2. 算法导论 — 15.5 最优二叉搜索树

    ###笔记 二叉搜索树满足如下性质:假设xxx是二叉搜索树中的一个结点.如果lll是xxx的左子树的一个结点,那么l.key≤x.keyl.key ≤ x.keyl.key≤x.key.如果rrr是x ...

  3. 【算法设计与分析】动态规划:最优二叉搜索树

    最优二叉搜索树问题的问题提出是,设S={x1, x2, -, xn}是一个由n个关键字组成的线性有序集,(a0, b1, a1, -, bn, an) 为集合S的存取概率分布,表示有序集S的二叉搜索树 ...

  4. 动态规划思想——最优二叉搜索树问题(附完整的代码)

    问题: 最优二叉搜索树问题的问题提出是,设S={x1, x2, ..., xn}是一个由n个关键字组成的线性有序集,(a0, b1, a1, ..., bn, an) 为集合S的存取概率分布,表示有序 ...

  5. 算法:最优二叉搜索树

    算法设计第五次作业part2 1.纸面题:对最优二叉树和矩阵连乘两种算法验证四边形法则,如果符合四边形法则则举几个正例,如果不符合则举几个反例 四边形法则 i<i'j<j'w(i,j)+w ...

  6. 《算法导论》15.5 最优二叉搜索树(含C++代码)

    一.问题背景和描述 给定一个n个不同关键字的已排序的序列K=<k1,k2, - kn>(因此k1<k2<-<kn),我们希望用这 些关键字构造一棵二叉搜索树.对每个关键字 ...

  7. 算法实验 最优二叉搜索树

    最优二叉搜索树 最优二叉搜索树 问题描述 问题分析 代码 问题描述 二叉搜索树我们都知道,左子树结点的值都小于根结点,右子树结点的值都大于根节点.如果某个结点没有左子树或右子树,那么在对应的位置上加一 ...

  8. 动态规划最优二叉搜索树C语言,【算法导论】动态规划之“最优二叉搜索树”...

    详解动态规划之"最优二叉搜索树" 之前两篇分别讲了动态规划的"钢管切割"和"矩阵链乘法",感觉到了这一篇,也可以算是收官之作了.其实根据前两 ...

  9. 算法设计与分析--最优二叉搜索树(Python)

    最优二叉搜索树: 给定一个n个不同关键字的已排序的序列K=<k1,k2,-,kn>(因此k1<k2<-<kn)我们希望用这些关键字构造一棵二叉树.对每个关键字ki,都有一 ...

最新文章

  1. 使用Java企业级技术开发大型系统(3)
  2. C++学习之路 | PTA乙级——1092 最好吃的月饼 (20 分)(精简)
  3. Windows编程—控制面板程序显示信息修改(程序图标、名称、链接等)
  4. Java中的形参和实参的区别以及传值调用和传引用调用
  5. Api demo源码学习(4)--App/Activity/Dialog --Activity以Dialog形式呈现
  6. linux下mysql数据的导出和导入
  7. 51单片机流水灯方法大全
  8. Oracle 后台进程详解
  9. be 动词 、 一般动词的过去式
  10. Caused by: java.lang.NoSuchMethodError
  11. java mp3转midi_javax_sound_midi-_player 将mid音频文件用java来实现它的播放和使用 - 下载 - 搜珍网...
  12. 斩获新一轮数亿元融资,Seesaw这杯创意咖啡里有多少“泡沫”?
  13. Altium设置菜单之系统菜单
  14. Modelsim中出现Syntax error, unexpected non-printable character错误
  15. MineCraft | 命令附魔
  16. Day14.网络编程入门及其应用
  17. linux shift f11,然后按下CTRL+SHIFT+F11组合键
  18. 顶!Python 与 Excel 终于在一起了
  19. 深入分析事物以及什么是分布式事物?
  20. 虚幻引擎图文笔记:蓝图中二项切换节点(Flip Flop)的用法

热门文章

  1. Spring框架IOC基础及XML的配置 第二章
  2. 电脑有网(如可以登QQ),但浏览器连不上网络
  3. python3.5使用教程_python3.5爬虫入门教程
  4. python读取idx_通过Python从.idx3-ubyte文件或GZIP中提取图像 - python
  5. 员工信息管理系统(JavaWeb结课项目)
  6. 一个数异或同一个数两次,结果还是那个数
  7. 【机器学习实战】利用sklearn中的逻辑回归对癌症分类预测-良/恶性乳腺癌肿瘤预测
  8. 【ChatGPT的小妙招】结合Excel的vbs开发者工具达成对Excel文件的处理
  9. 微信域名防封网站防拦截新方案
  10. linux 性能测试 antutu,跑分软件测试性能提升幅度