最优二分检索树

简介:   前面给出了二分检索树的定义,下图给出了关于保留字的一个子集的两棵二分检索树。   为了确定标识符x是否在一棵二分检索树中出现,将x先与根比较,如果X比根中标识符小,则检索在左子树中继续;如果x等于根中标识符,则检索成功地终止;否则检索在右子树中继续下去。

  前面给出了二分检索树的定义,下图给出了关于保留字的一个子集的两棵二分检索树。

  为了确定标识符x是否在一棵二分检索树中出现,将x先与根比较,如果X比根中标识符小,则检索在左子树中继续;如果x等于根中标识符,则检索成功地终止;否则检索在右子树中继续下去。上述步骤可以形式化为过程Search。

Line void Search (BinaryTree T,elemType x,int i) {
//在二分检索树T上查找x,树的每个结点有三个信息段:LChild,IDent
//和RChild。如果x不在T中,则置i=0,否则将i置成使得IDent(i)=x
1 i = T;
2 while(i!=0) {
3 if(x=IDent[i] {return IDent[i]};//检索成功
4 else
5 if(x<IDent[i] { i=Lchild[i]};//检索左子树
6 else { i=Rchild[i]}; //检索右子树
7 };//while
8 }//Search

已知一个固定的标识符集合,希望产生一种构造二分检索树的方法。可以预料,同一个标识符集合有不同的二分检索树,而不同的二分检索树有不同的性能特征。

下面说说不成功检索的含义:为了得到二分检索树的成本函数,在这棵检索树的每一棵空子树的位置上加上一个虚构的结点,即外部结点,它们在图4.2中画成方框。所有其它结点是内部结点。如果一棵二分检索树表示n个标识符,那么正好有n个内部结点和n+1个外部结点。每个内部结点代表一次成功检索可能终止的位置。每个外部结点表示一次不成功检索可能终止的位置。

 

二分检索树的预期成本可用公式表示如下:
ΣP(i)*level(ai) + ΣQ(i)*(level(Ei)-l)
    1≤i≤n 0≤i≤n
定义标识符集(a1,a2,…,an)的最优二分检索树是一棵使(4.1)式取最小值的二分检索树。

如果T是最优的,则(4.2)式必定是最小值。进而COST(L)对于包含a1,a2,…,ak-1和E0,El,…,Ek-1的所有二分检索树必定是最小值,同理COST(R)也必定是最小值。
如果用C(i,j)表示包含ai+1,…,aj和Ei,…,Ej的最优二分检索树的成本,那么要让T是最优的,就必须有:
              COST(L) = C(0,k-1)和COST(R) = C(k,n)
              而且应该选择k使得 P(k) + C(0,k-1) + C(k,n) + w(0,k-1) + w(k,n) 取最小值。

因此,关于C(0,n)有
C(0,n) = min {c(0,k-1) + C(k,n) + P(k) + w(0,k-1) + w(k,n)}
0<k≤n
将(4.3)一般化,对任何C(i,j)则有
C(i,j) = min {C(i,k-1) + C(k,j) + P(k) + W(i,k-1) + W(k,i)}
i<k≤j
= min {C(i,k-1) + C(k,j)+W(i,j)}
i<k≤j

用下列步骤解(4.4)式可得C(0,n)。
首先计算所有使得j-i=1的C(i,j)(注意C(i,i)=0且W(i,i)=Q(i),0≤i≤n);
接着计算所有使得j-i=2的C(i,j);
然后计算j-i=3的所有C(i,j),等等。
如果在这计算期间,记下每棵Tij树的根R(i,j),那么最优二分检索树就可以由
这些R(i,j)构造出来。
需要指出的是,R(i,j)是使(4.4)式取最小值的k值。

 

下面举个例子:找最小成本二分检索树

Line void OBST(P,Q,n) {
//给定几个互异的标识符a1<a2<…<an。已知成功检索的概率P(i),1≤i≤n,
//不成功检索概率Q(i),1≤i≤n。此算法对标识符ai+1,…,an计算最优二分
//检索树Tij的成本C(i,j)还计算Tij的根R(i,j),Tij的权W(i,j)。
float P[n], Q[n], C[n][n], w[n][n];int R[n][n];
1 for(i=0;i<n;i++) {
2 (w(i,i),R(i,i),C(i,i)) = (Q(i),0,0); //置初值
3 (w(i,i+1),R(i,i+1),C(i,i+1)) = (Q(i)+Q(i+1)+P(i+1), i+1, Q(i)+Q(i+1)+P(i+1));
//含一个结点的最优树
4 };//for
5 (w(n,n),R(n,n),C(n,n)) = (Q(n),0,0);
6 for(m=2;m<=n;m++) { //找有m个结点的最优树
7 for(i=0;i<=n-m;i++) {
8 j = i+m;
9 w(i,j)=W(i,j-1) + P(j) + Q(j);
10 K = 区间[R(i,j-1),R(i+1,j)]中使{C(i,r-1)+C(r,j)}取最小值的r值;
//用Knuth的结果解(4.4)式
11 C(i,j) = w(i,j) + C(i,k-1) + C(k,j);
12 R(i,j) = k;
13 };//for
14 };//for
15} //OBST

 

 

相关文章
|
2月前
|
算法 开发者 索引
二分算法详解
本文介绍了二分查找及其相关问题的解决方法,包括基本的二分查找、查找元素的第一个和最后一个位置、求平方根、搜索插入位置、寻找峰值和旋转数组中的最小值等问题。通过详细分析每种情况下的二分查找策略,如循环条件、区间划分及特殊情况处理,提供了清晰的代码实现。适用于算法初学者和需要巩固二分查找技巧的开发者。
97 18
二分算法详解
|
7月前
|
算法 测试技术 C++
【双指针】【C++算法】1537. 最大得分
【双指针】【C++算法】1537. 最大得分
|
7月前
|
算法 C++
动态规划的时间复杂度优化
动态规划的时间复杂度优化
|
7月前
|
算法 Java C++
非启发式算法——二分、三分搜索算法
非启发式算法——二分、三分搜索算法
225 0
|
算法 测试技术 C#
C++二分算法:平衡子序列的最大和
C++二分算法:平衡子序列的最大和
|
存储 算法 Python
秒懂算法 | 子集树模型——0-1背包问题的回溯算法及动态规划改进
给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为W。一种物品要么全部装入背包,要么全部不装入背包,不允许部分装入。装入背包的物品的总重量不超过背包的容量。问应如何选择装入背包的物品,使得装入背包中的物品总价值最大?
744 0
秒懂算法 | 子集树模型——0-1背包问题的回溯算法及动态规划改进
|
机器学习/深度学习 算法 Java
排序不等式算法
排序不等式算法
排序不等式算法
|
存储 算法
LeetCode 435. 无重叠区间(贪心算法,动态规划)
LeetCode 435. 无重叠区间(贪心算法,动态规划)
128 0
LeetCode 435. 无重叠区间(贪心算法,动态规划)
AcWing 3797. 最大化最短路(排序优化+最短路)
AcWing 3797. 最大化最短路(排序优化+最短路)
87 0
|
人工智能 算法
排序不等式(贪心)
复习acwing算法基础课的内容,本篇为讲解基础算法:贪心——排序不等式,关于时间复杂度:目前博主不太会计算,先鸽了,日后一定补上。
107 0
排序不等式(贪心)