动态规划 最优二叉搜索树

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

摘要

动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解,每个解都对应一个值,要求找到具有最优值的解。其基本思想是将待求解问题分解成若干个子问题,先求解子问题,并把所有已解子问题的答案记录到一个表中,而不考虑这些子问题的答案以后是否被用到。用动态规划算法来求解最优二叉搜索树问题,可以描述为对于有序集S及S的存取概率分布(a0,b1,a1,…, bn,an),在所有表示有序集S的二叉搜索树中找出一棵开销最小的二叉搜索树。

动态规划算法的有效性依赖于问题本身具有最优子结构性质和子问题重叠性质。最典型的就是路由器中的路由搜索引擎查找一条指定的路由最坏情况下最多只用查找31次。

该文给出了用动态规划算法构造最优二叉搜索树的详细步骤,并用C++语言具体实现了该算法,用一定的空间换取时间,提高了解决本问题的效率。

关键词:动态规划,最优二叉搜索树,最优子结构

目录

1 问题描述 (1)

2 问题分析 (2)

3 算法设计 (3)

4 算法实现 (4)

5 测试分析 (6)

结论 (7)

参考文献 (8)

1 问题描述

给定一个有序序列K={k1

2 问题分析

最优二叉搜索树问题具有最优子结构性质。证明:设Tij是有序集{xi,…,xj}关于存取概率分布(ai-1,bi,…,bj,aj)的一棵最优二叉搜索树,平均路长为pij。Tij的根结点存储元素xk。其左右子树Tl和Tr的平均路长分别为pl和pr。由于Tl是关于集合{xi,…,xk-1}的一个二叉搜索树,故pl≥pi,k-1。如果pl>pi,k-1,那么用Ti,k-1替换Tl可得到平均路长比Tij更小的二叉搜索树。这与Tij 是最优二叉搜索树相矛盾。所以,左子树Tl是一棵最优二叉搜索树,同理可证右子树Tr也是一棵最优二叉搜索树,即最优二叉搜索树的子树也是最优二叉搜索树。建立递归关系式若最优二叉搜索树Ti,j的根结点为k,最小平均路长为pi,j,m[i,j]表示Ti,j的开销,则有m[i,j]=wi,jpi,j,其中,可建立下列递归关系:

M[i,j]=bk+(m[i,k-1]+wi,k-1)+ (m[k+1,j]+wk+1,j)

而wi,j=bk+wi,k-1+wk+1,j

则m[i,j]=wi,j+m[i,k-1]+m[k+1,j](1)

将k=i+1,i+2,…,j分别代入<1>式,选取使m[i,j]达到最小的K,这样递归关系式改为:

m[i,j]=wi,j+min{m[i,k-1]+m[k+1,j]}m[i,i-1]=0,1≤i≤n

解递归关系,m[1,n]就是所求的最优值。将对应于m[i,j]的断开位置k记录在s[i,j]中(也称为根表,记录子树的根),以便构造最优解。根据记录的最优断开位置s[i,j],可以容易地构造出最优解。

3算法设计

寻找最优子结构。一个最优二叉树的子树必定包含连续范围的关键字ki~kj,1<=i<=j<=n,同时也必须含有连续的虚叶子节点di-1~dj。如果一棵最优二叉查找树T有一棵含有关键字ki~kj的子树T',那么,T'也是一棵最优查找树,这通过剪贴思想可以证明。

现在开始构造最优子结构:在ki~kj中,选定一个r,i<=r<=j,使以kr为根,ki~k(r-1)和k(r+1)~kj为左右孩子的最优二叉树。注意r=i或者r=j的情况,表示左子树或右子树只有虚叶子节点。

定义e[i,j]为一棵包含关键字ki~kj的最优二叉树的期望代价。当j=i-1时没有真实的关键在,只有虚叶子节点d(i-1)。

于是:

当j=i-1时,e[i,i-1]=q(i-1)。

当j>=i时,需要选择合适的kr作为根节点,然后其余节点ki~K(r-1)和k(r+1)~kj构造左右孩子。这时要考虑左右孩子这些节点成为一个节点的子树后,它的搜索代价的变化:根据E[T]的计算,得知它们的期望代价增加了“子树中所有概率的总和”w。

w[i,j]= pl // 对每个l=i~j

+ql //对每个l=i-1~j

于是当j>=i时,e[i,j]=pr + (e[i,r-1]+w[i,r-1])+(e[r+1,j]+w[r+1,j]) = e[i,r-1] + e[r+1,j]+w[i,j];

4 算法实现

计算最优二叉树的期望代价

e[i,j]= q(i-1) //如果j=i-1

min(e[i,r-1] + e[r+1,j]+w[i,j]),如果i<=j,其中i<=r<=j

w[i,j]=q(i-1) 如果j=i-1

w[i,j]=w[i,j-1]+pj+qj 如果i<=j

3.代码实现

view plaincopy to clipboardprint?

#include

using namespace std;

#define MAXNUM 100

#define MAX 65536

//p中为有序关键字k1到k5的搜索概率,k1

double p[MAXNUM] = {0.00,0.15,0.10,0.05,0.10,0.20};

double q[MAXNUM] = {0.05,0.10,0.05,0.05,0.05,0.10};

void optimal_bst(double e[][MAXNUM],int root[][MAXNUM],double w[][MAXNUM],int n)

{

int i =0,j=0;

//针对左或右孩子为空树情况初始化

for(i = 1;i<=n+1;i++)

{

e[i][i-1] = q[i-1];

w[i][i-1] = q[i-1];

}

int l = 0;

//计算顺序如下:根据计算式:e[i,j] = e[i,r-1]+e[r+1,j 首先计算节点个数为1的最优二叉树的代价e[1,1],e[2,2]…… 接着计算节点个数为1的最优二叉树的代价e[1,2],e[2,3]…………最后计算结点个数为n的最优二叉树的代价e[1,n],利用之前保存的较少结点最优二叉树的结果。

for(l = 1;l<=n;l++)

相关文档
最新文档