动态规划 最优二叉搜索树Word格式文档下载.docx
《动态规划 最优二叉搜索树Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《动态规划 最优二叉搜索树Word格式文档下载.docx(6页珍藏版)》请在冰豆网上搜索。
给定一个有序序列K={k1<
k2<
k3<
……,<
kn}和他们被查询的概率P={p1,p2,p3,……,pn},要求构造一棵二叉查找树T,使得查询所有元素的总的代价最小。
对于一个搜索树,当搜索的元素在树内时,表示搜索成功。
当不在树内时,表示搜索失败,用一个“虚叶子节点”来标示搜索失败的情况,因此需要n+1个虚叶子节点{d0<
d1<
……<
dn}。
其中d0表示搜索元素小于k1的失败结果,dn表示搜索元素大于kn的失败情况。
di(0<
i<
n)表示搜索节点在ki和k(i+1)之间时的失败情况。
对于应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,其中<
E:
\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<
=j
w[i,j]=q(i-1)如果j=i-1
w[i,j]=w[i,j-1]+pj+qj如果i<
=j
3.代码实现
viewplaincopytoclipboardprint?
#include<
iostream>
usingnamespacestd;
#defineMAXNUM100
#defineMAX65536
//p中为有序关键字k1到k5的搜索概率,k1<
k4<
k5
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;
=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;
=n-l+1;
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])
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;
=6;
for(intj=0;
j<
=5;
j++)
cout<
<
e[i][j]<
"
;
endl;
}}
5测试分析
在二叉树中T内搜索一次的期望代价为:
(depth(ki)+1)*pi
//对每个i=1~n,搜索成功情况
+(depth(di)+1)*qi//对每个i=0~n,搜索失败情况
[i,j]=
q(i-1)
//如果j=i-1
w[i,j]=
q(i-1)如果j=i-1
w[i,j]=w[i,j-1]+pj+qj如果i<
结论
最优二叉搜索树是整个搜索成本最低的二叉搜索树。
具体来说就是:
给定键值序列K=<
k1,k2,...,kn>
,k1<
k2<
·
·
<
kn,其中键值ki,被搜索的概率为pi,要求以这些键值构建一颗二叉搜索树T,使得搜索的期望成本最低(搜索成本为检查的节点数)。
对于键值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.