MAX-HEAPIFY的最坏情况:“最坏的情况发生在树的底层正好是半满的时候”

时间:2011-07-28 13:12:17

标签: algorithm heap clrs

CLRS,第三版,第155页,给出了MAX-HEAPIFY,

"the worst case occurs when the bottom level of the tree is exactly half full"  

我想原因是在这种情况下,Max-Heapify必须通过左子树“向下浮动”。
但我无法得到的是“为什么半满”? 如果左子树只有一个叶子,Max-Heapify也可以向下浮动。那么为什么不把这视为最坏的情况?

2 个答案:

答案 0 :(得分:11)

阅读整个背景:

  

子项的子树每个都有2n / 3的大小 - 最坏的情况发生在树的最后一行正好是半满

由于运行时T(n)是通过树中的元素数量(n)来分析的,并且递归步进到其中一个子树中,我们需要找到数字的上限子树中相对于n的节点数,这将产生T(n) = T(max num. nodes in subtree) + O(1)

子树中节点数最差的情况是最后一行在一侧尽可能充满,而在另一侧尽可能为空。这被称为半满。左侧子树大小将受2n/3限制。

如果您提议只有少数节点的情况,那么这是无关紧要的,因为所有基本情况都可以被视为O(1)并被忽略。

答案 1 :(得分:0)

我知道已经有一个可以接受的答案,但是对于那些有同样问题并且仍然有点困惑(就像我一样)或者不清楚的人 - 这里有更长更详细的解释。< /p>

虽然这听起来可能很无聊或多余,但我们必须非常清楚确切的定义,因为通过关注细节 - 很有可能当你这样做时,证明事情变得容易得多。

从 CLRS 6.1 节开始,(二进制)堆数据结构是一个数组对象,我们可以将其视为近乎完整的二叉树

来自维基百科,在一棵完全二叉树中,每一层(可能除了最后一层)都被完全填充,并且最后层中的所有节点都 >尽量离开

另外,来自维基百科,平衡二叉树是一种二叉树结构,其中每个节点的左右子树的高度相差不超过1。

因此,与根相比,左右子树的高度最多可以相差 1。

现在,考虑一棵树T,让左子树的高度=h+1,右子树的高度=h

MAX_HEAPIFY 中最坏的情况是什么?最坏的情况是,我们最终在尝试维护堆属性的同时进行了更多的比较和交换。

如果 MAX_HEAPIFY 算法运行并且递归通过最长路径,那么我们可以考虑可能的最坏情况。

好吧,所有最长的路径都在左子树中(因为它的高度是 h+1)。为什么不是正确的子树?记住定义,最后层的所有节点必须尽可能左边

所以,为了获得更多的最长路径,我们应该让 left 子树全满(为什么?这样我们就可以有更多的路径可供选择并选择提供最坏情况时间)。由于左子树的高度为 h+1,因此它将有 2^(h+1) 个叶节点,因此从根开始有 2^(h+1) 条最长的路径。这是树 T 中最长路径的最大可能数量(h+1 高度)。

这是最坏情况下树结构的 image

从上图中,考虑黄色(左)和粉红色(右)子树各有 x 个节点。粉色部分为完全右子树,黄色部分为不包括最后一层的左子树。

注意黄色(左)和粉红色(右)子树的高度为 h。

现在,从一开始,我们就认为左子树作为一个整体的高度为 h+1(包括黄色部分和最后一层),如果我可以问,我们有多少个节点在最后一层即黄色部分下方添加,使左子树完全填满?

嗯,黄色部分的最底层有 ⌈x/2⌉ 个节点(具有 n 个节点的树/子树中的叶子总数 = ⌈n/2⌉;对于证明访问 this链接),现在如果我们向这些节点/叶子中的每一个添加 2 个子节点,=> 总共添加了 x (≈x) 个节点(如何?⌈x/2⌉ 叶子 * 2 ≈ x 个节点)。

通过这个添加,我们制作了高度为 h+1(高度为 h 的黄色部分 + 添加的最后一层)和 FULL 的左子树,因此满足最坏情况的标准。

由于左子树是满的,整个树是半满的。

现在,最重要的问题——为什么我们不添加更多节点或在正确的子树中添加节点?好吧,那是因为现在如果我们倾向于添加更多节点,则必须将节点添加到右子树中(因为左子树已满),这反过来会更平衡树.现在,随着树开始变得更加平衡,我们倾向于朝着最好的情况而不是最坏的情况发展。

另外,我们总共有多少个节点?

树的总节点数 n = x(来自黄色部分)+ x(来自粉色部分)+ x(黄色部分下方最后一层的添加)= 3x

注意,作为副产品,左子树总共包含最多 2x 个节点,即 2n/3 个节点 (x = n/3)。