问题描述:

 维基百科定义:

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. 代码覆盖测试工具Kcov简介及使用
  2. Rtx 实时通知实现
  3. 交换机组最常见的8大故障及解决方法
  4. 【Quartz】深入Job、JobDetail、JobDataMap、Trigger
  5. C/C++语言函数学习(4)字符串处理函数
  6. linux命令之which
  7. matlab 两点划线,matlab学习2-画线
  8. DG SG childSG fatherSG
  9. IIS 添加mime 支持 apk,exe,.woff,IIS MIME设置 ,Android apk下载的MIME 设置 苹果ISO .ipa下载mime 设置...
  10. mysql optimize 用法_mysql中OPTIMIZE TABLE的作用
  11. 玩水——西沙:在海的远处,水是那么蓝那么清
  12. php小炒花生米,花生(炒)的做法_花生(炒)怎么做好吃_花生(炒)的家常做法大全【美食杰】...
  13. “双一流”大学生们最爱看的计算机类书籍是它们
  14. 怎样在计算机上注册dll文件,注册dll文件【搞定步骤】
  15. HandlerSocket
  16. MySQL使用order by默认是升序还是降序?
  17. 我的Foobar2000定制版本
  18. 迪赛智慧数——柱状图(堆叠极扇图):近5年各行业员工离职率
  19. 基于JNA(Java Native Access)实现RFID单卡、多卡读取以及写入。
  20. java中的正则matches方法和find方法的区别

热门文章

  1. nodejs读取远程共享文件
  2. 浅析ReentLock的使用
  3. Introduce·哲学核心期刊推荐之《华东师范大学学报:哲学社会科学版》
  4. CleanMyMac X2023标准版解锁完整版本Mac电脑清理专家
  5. 电脑出现DuiLib资源加载失败的解决办法
  6. 【笔记】《由浅入深SCF无服务器云函数实践》
  7. 2022-10-13 Android APP 全屏幕显示全透明沉浸式主题android:theme样式 Theme.TranslucentTheme
  8. Python人体肤色检测
  9. 交叉线、直通线背后掩藏着什么?
  10. 联发科MT76x8使用1-芯片对比