动态规划 最优二叉搜索树.docx

上传人:b****6 文档编号:4369290 上传时间:2022-12-01 格式:DOCX 页数:6 大小:18.94KB
下载 相关 举报
动态规划 最优二叉搜索树.docx_第1页
第1页 / 共6页
动态规划 最优二叉搜索树.docx_第2页
第2页 / 共6页
动态规划 最优二叉搜索树.docx_第3页
第3页 / 共6页
动态规划 最优二叉搜索树.docx_第4页
第4页 / 共6页
动态规划 最优二叉搜索树.docx_第5页
第5页 / 共6页
点击查看更多>>
下载资源
资源描述

动态规划 最优二叉搜索树.docx

《动态规划 最优二叉搜索树.docx》由会员分享,可在线阅读,更多相关《动态规划 最优二叉搜索树.docx(6页珍藏版)》请在冰豆网上搜索。

动态规划 最优二叉搜索树.docx

动态规划最优二叉搜索树

摘要

动态规划算法通常用于求解具有某种最优性质的问题。

在这类问题中,可能会有许多可行解,每个解都对应一个值,要求找到具有最优值的解。

其基本思想是将待求解问题分解成若干个子问题,先求解子问题,并把所有已解子问题的答案记录到一个表中,而不考虑这些子问题的答案以后是否被用到。

用动态规划算法来求解最优二叉搜索树问题,可以描述为对于有序集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

对于一个搜索树,当搜索的元素在树内时,表示搜索成功。

当不在树内时,表示搜索失败,用一个“虚叶子节点”来标示搜索失败的情况,因此需要n+1个虚叶子节点{d0

其中d0表示搜索元素小于k1的失败结果,dn表示搜索元素大于kn的失败情况。

di(0

对于应di的概率序列是Q={q0,q1,……,qn}。

在最有二叉搜索树问题是指已给出一株二叉树的中序遍历(或需要你全排列枚举),以及每个节点搜索概率,搜索到一层花费1,问如何安排这颗二叉树使搜索花费的期望值最小。

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,其中

\2008学术交流\200学术交流第四卷第八期(2008总第35期)\第1次96篇\1.3软件设计开发\tr01.tif>,可建立下列递归关系:

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.代码实现

viewplaincopytoclipboardprint?

#include

usingnamespacestd;

#defineMAXNUM100

#defineMAX65536

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

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

doubleq[MAXNUM]={0.05,0.10,0.05,0.05,0.05,0.10};

voidoptimal_bst(doublee[][MAXNUM],introot[][MAXNUM],doublew[][MAXNUM],intn)

{

inti=0,j=0;

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

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

{

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

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

}

intl=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++)

{

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

{

j=i+l-1;

e[i][j]=MAX;

w[i][j]=w[i][j-1]+p[j]+q[j];

for(intr=i;r<=j;r++)

{

doublet=0;

t=e[i][r-1]+e[r+1][j]+w[i][j];

if(t

{

e[i][j]=t;

root[i][j]=r;

}

}

}

}

}

intmain()

{

doublee[MAXNUM][MAXNUM];

introot[MAXNUM][MAXNUM];

doublew[MAXNUM][MAXNUM];

optimal_bst(e,root,w,5);

for(inti=1;i<=6;i++)

{

for(intj=0;j<=5;j++)

{

cout<

}

cout<

}}

5测试分析

在二叉树中T内搜索一次的期望代价为:

(depth(ki)+1)*pi //对每个i=1~n,搜索成功情况

+(depth(di)+1)*qi//对每个i=0~n,搜索失败情况

[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

结论

最优二叉搜索树是整个搜索成本最低的二叉搜索树。

具体来说就是:

给定键值序列K=,k1

对于键值ki,如果其在构造的二叉搜索树里的深度(离开树根的分支数)为depthT(ki),则搜索该键值的成本=depthT(ki)+1(需要加上深度为0的树根节点)。

由于每个键值被搜索的概率分别为pi=1,2,3…,n。

本算法分析与设计课程设计是综合分析和理解动态规划算法,综合运用C、C++或JAVA等程序设计语言,设计的过程也是一个不断摸索的过程。

只有对所作题目有了清楚的认识和理解,有了思想上的充分准备,才能在设计过程中“胸有成竹”。

所以我们对题目进行了比较详尽的考虑。

当实际操作过程中遇到这样那样的困难,就通过查看资料、上网等方式解决。

通过这次课程设计,我们对动态规划算法有了更深的认识,同时也更加熟练了C、C++和JAVA程序设计语言的运用,是开发人员必不可少的有力工具。

同时,我们学到了如何用算法的思想分析一个给定的问题,最终动手解决问题。

在整个过程中,需要不断的调试,更改代码,当中,我们遇到了很多棘手问题。

在不断思考、调试后,不仅锻炼了我的实际动手能力,更锻炼了我们发现问题、分析问题的能力。

参考文献

[1]孙雄勇.《VisualC++6.0实用教程》.北京:

中国铁道出版社,2004

[2]谭浩强编著.《C++面向对象程序设计》.北京:

清华大学出版社,2006

[3]王晓东编著.《计算机算法设计与分析》.北京:

电子工业出版社,2007.5

[4]常友渠.动态规划的探讨与研究[M].重庆电力高等专科学报,2008.9.

[5]龚雄兴,堆与动态规划[M],湖北襄樊学院,2003.

[6]张洁,朱莉娟.贪心算法与动态规划的比较[M].新乡师范高等专科科学学报,2005.9.

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 小升初

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1