判断二叉树是否为完全二叉树算法_理解Knuth大神对最优二叉树的巧妙改进

3d100a992ba640f46fdd6976d8f8c0a6.png

这篇文章是关于本学期课程《数据结构》课本中一个问题的补充。早在一个月前就被大佬ZWC同学怂恿写这篇博客,但是由于太懒一直拖到现在。

这个问题源自Cormen《算法导论》对应章节的一个课后题,解法源自图灵奖得主D. E. Knuth在1970年发表的一篇论文。(所以说这个课后题真的有点难!)先简单地说一说最优二叉树的原始算法,再看看Knuth 对这个算法的refinement——从

的巧妙改进。

Part 1 问题描述

最优二叉树(Optimum Binary Search Tree) 指对于给定节点构造出的权重和最小的二叉树。设有带权全序节点集合

,其中
为节点对应的权重。我们的任务是构造一棵二叉树
使得其权重和:

达到最小,其中

是第i个节点在二叉树中的深度。注意,为了使算法本身的特性更加明晰,我们去掉最优二叉树问题中“找不到所需节点”时的备用"dummy keys", 也就是说,每次查找的节点都一定可以被查找得到的。更加一般的OBST问题可以在参考文献中进一步了解。

一个简单的例子是字典的编排:把单词连同它出现的频率作为节点放在二叉树中。当我们需要查询一个单词时,从根节点出发按照二叉树查找的方法找到这个单词。一个直观的判断是:频率出现高的单词应当放得更加靠近根位置,不太可能出现的单词要放在尽可能深的位置。事实上,这个猜测并不完全正确。

考虑由A, B, C三个节点,他们的序关系A<B<C。当它们的权重按照下面两种分配方式进行时,最优二叉树分别为:

6427f11ecaac51cbca4e0e521695290f.png
两种情况

注意,在第二种情形下,B节点的权重最小,但是它却是最优二叉树的根节点。所以构造最优二叉树的方法一般来说没有什么捷径可言。

Part 2 原始算法(枚举法)

原始的最优二叉树求法近似于枚举法。对于任意一个最优二叉树

, (以下简称OBST),它的任何以节点i作为根节点的子树
也都是最优二叉树(若不然,用最优树
嫁接在节点i处,得到权重更小的二叉树
)。另外,注意到由搜索二叉树的定义,所有序关系相连的节点在二叉树中也必然相连接——也就是说,如果我们用
表示包含从i到j所有节点的子树,那么
恰恰就是所有子树的集合——因为不可能存在一个子树,它包含序关系不连续的节点。

这样一来,我们所要做的就是输出一个矩阵

,它的(i , j)元素就是子树
的根节点:这个矩阵完整地描述出来我们需要的最优二叉树。

于是对于给定的长度

, 我们让i,j指标跑遍所有可能的取值(这便蕴含了两个for循环,复杂度已经升至
);对于每一组(i , j)尝试所有
的节点,让它们一一作为
的根节点计算
的权重和。从这个思路来看,我们需要一个有效计算任何一个子树权重和的递归算法。

假设已经得到了

根节点
的左右子树的权重和,分别为
. 记:

则权重和是左边加右边加中间:

之所以出现w项,是因为把k节点加入二叉树时,我们其实把左右子树中每一个节点的深度都加了1个单位。这样我们就可以利用长度小于l的结果计算长度为l的结果了。算法的伪代码表示如下:

Optimal Binary Search Tree (vector a[i], vector p[i]):
1    new matrix e[i][j] and w[i][j] and r[i][j], #i,j from 1 to n
2    for i from 1 to n: 
3        e[i][i] = p[i]
4        w[i][i] = p[i]
5    for l from 2 to n: #子树长度从2开始
6        for i in range(n):
7            j = i + l -1
8            e[i][j] = infty #初始化
9            w[i][j] = w[i][j-1] + p[j]  #by definition
10            for k from i to j:
11                 tmp = e[i][r-1] + e[r+1][j] + w[i][j]  #(*)式计算权重和
12                 if t < e[i][j]:
13                     e[i][j] = tmp
14                     r[i][j] = k
15     return e, r

注意到这个程序的输出是上面提到的矩阵,和最终计算的权重和。第五行开始的for循环固定了子树的长度,第六行跑遍所有长度为l 的子树;第10行的for循环则是一个一个尝试范围内的节点作为子树的根节点并计算权重和,类似于枚举法。实现的代码参见:

Optimal Binary Search Tree | DP-24 - GeeksforGeeks​www.geeksforgeeks.org

显然,这个算法的时间复杂的是三次方的,因为前后一共嵌套三个跑遍所有取值的for循环。

Part 2 Knuth的改进

有一说一,Knuth的改进并不是本质的。这个改进通过观察加入一个节点时整个二叉树的变化出一般规律(但是我认为发现这个规律需要极高的天才);这个规律告诉我们:在上述第十行的循环里,并不需要尝试所有的i , j范围内的节点,因为有些节点不可能成为最优子树的根节点!

沿用上边的记号,我们先证明下面的引理:

Lemma 考虑在最优二叉树

上增加0权重节点
, 则新的最优二叉树可以为如下形式:在
右下末尾的节点上接上第n个节点。

(注意,此处的n指标仍然包含节点key值的序关系,也就是说,第n个节点是所有n个节点中key值最大的。)

Proof: 记

为最优树
的根节点,换句话说,我们需要证明的是以下两点:

第一条的意思是,增加第n个0权重节点不会改变整个树的权重和:这是显然的。

第二条的意思是,增加一个0权重最大节点,所有

子树的根节点和上一步保持一致;这两条蕴含了原命题假设。事实上,

(利用第一条)

另一方面,多加一个节点不会使得最优树的总权重降低:

,意即
最小可以达到
但是不会比这更小,而这个最小值可以在根节点保持不变的情况下取到,所以有
。 Q.E.D.

Remark: 这个引理保证了主要定理归纳法的前提。证明看似平凡,是因为我简化了问题:原问题还包含着找不到key时返回的dummy keys,它们构成最优二叉树的所有叶子结点,情况更加复杂。

下面是核心定理:

Theorem: 对于一个最优二叉树

, 加入最大的第n个节点不会使得最优二叉树的根节点左移。换句话说,恒成立如下不等式:

其中的不等号指的是key值的序关系。也就是说,左边加小节点,根节点不变大;右边加大节点,根节点不变小。这里的大小指的是key值的大小。

先来看这个性质如何将复杂度降为

。对于固定的i和j,上面的不等式给出了介于
之间的哪些节点有可能成为ij子树的根节点:

c4353f5a27326a5d814ec07fe454d1a6.png
一个输出结果例子

也就是说,在伪代码第10行开始的循环中,我们不需要一个一个检查所有的节点是否可以成为

的根节点,而是只需用上一步算出来的上下界先排除掉一部分节点。 上图是一个最优二叉树的输出结果,每一个对角线(也就是上图中横着的一行)代表一个固定的长度l;当我们算第k个对角线时,按照程序,k-1行已经都得到:比如算
的根节点时,无需计算就得知根节点一定是节点2. 固定l,对所有尝试次数求和我们有:

这其实是一个裂项和!为更清楚一些,设l=4,写出求和式:

所以结果是一个常数,而非n.

下面给出定理的证明:

Proof: 在引理中我们已经得知当新节点为零权重时,结论成立。下面用归纳法证明对于任意大的新节点权重,上式仍然成立。

为最优树的临界值,即,对于
, 最优树
; 对于
, 最优树
。反设随着
在这个范围内增加的过程中,
,也就是根节点发生了左移。我们断言,对于两棵树的末端节点深度,有:

其中d和d' 分别为

中节点的深度函数。事实上,如果
(不会相等),设
,则由
是最优树知:

由(1)和

:

足够小使得
, 代换上式最右项即得到和(2)矛盾。

这意味着在

增加前就优于
, 矛盾。

考虑两棵树的右边:

3734e7c0f6ceb41dd959fde2b785fb74.png

由反设假设,

,
. 对
为根的两棵子树应用归纳假设(后者可以看做是前者在左边加了小节点)知:
. 如果不等号严格成立,我们又有

另一方面,由于

,
, 故必有k使得
, 两棵树的右边节点在k处重合。用
中右子树代替
中对应
右子树,得到新的树
. 这棵树的总权重和
相等,根节点和
相同。

事实上,分别记

的上述子树为
. 由于
中加入
子树的地方和
相同,
子树内的节点权值和
显然相同,则只需说明来自
部分节点权重和与
也相同。将子树看做原树的点,则
是较大
时最优树,
是较小
时的最优树; 由于前者相比于后者根节点发生左移,应用归纳假设知
, 反向不等式显然成立。

故不需要让节点左移。Q.E.D.

ps: 十分感谢ZWC同学对本文的校对,以及给我指出最后一个命题的正确证明。

参考文献:

  1. D. E. Knuth: Optimum Binary Search Tree, Acta Informatica 原文链接:
www.inrg.csie.ntu.edu.tw/algorithm2014/presentation/Knuth71.pdf​www.inrg.csie.ntu.edu.tw

2. Thomas H. Cormen: Introduction to Algorithms, 3rd edition, chapter 15.5, mit express.

相关书籍:

  1. 严蔚敏吴伟民《数据结构》清华大学出版社
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值