Max-Heapify 中最坏的情况——你如何得到 2n/3?

Posted

技术标签:

【中文标题】Max-Heapify 中最坏的情况——你如何得到 2n/3?【英文标题】:Worst case in Max-Heapify - How do you get 2n/3? 【发布时间】:2012-02-24 07:51:09 【问题描述】:

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

每个孩子的子树的大小最多为 2n/3——最坏的情况 当树的底层恰好是半满时发生。

我明白为什么当树的底层正好是半满时最糟糕。而且这个问题也有回答worst case in MAX-HEAPIFY: "the worst case occurs when the bottom level of the tree is exactly half full"

我的问题是如何获得 2n/3?

为什么如果底层是半满的,那么子树的大小最多是2n/3?

如何计算?

谢谢

【问题讨论】:

这个博客提供了一个简单的计算:bit.ly/138f43F。 【参考方案1】:

在每个节点恰好有 0 个或 2 个子节点的树中,具有 0 个子节点的节点数比具有 2 个子节点的节点数多 1。说明:高度 h 的节点数为 2^h,由几何级数的求和公式等于(从高度0到h-1的节点之和)+ 1;并且从高度 0 到 h-1 的所有节点都是恰好有 2 个孩子的节点

    ROOT
  L      R
 / \    / \
/   \  /   \
-----  -----
*****

设k为R中的节点数。L中的节点数为k + (k + 1) = 2k + 1。总节点数为n = 1 + (2k + 1) + k = 3k + 2(根加 L 加 R)。该比率为 (2k + 1)/(3k + 2),以 2/3 为界。没有小于 2/3 的常数起作用,因为 k 趋于无穷时的极限是 2/3。

【讨论】:

是的,我明白了,你的意思是 L / n = 2/3 哇。那很深。你自己是怎么想出来的?【参考方案2】:

Understand the maximum number of elements in a subtree happens for the left subtree of a tree that has the last level half full.Draw this on a piece of paper to realize this.

一旦清楚了,2N/3的界限就很容易得到了。

让我们假设树中的节点总数为 N。

树中的节点数 = 1 +(左子树中的节点数)+(右子树中的节点数)

对于树的最后一层半满的情况,如果我们假设右子树的高度为 h,那么左子树的高度为 (h+1):

左子树的节点数=1+2+4+8....2^(h+1)=2^(h+2)-1 .....(i)

右子树的节点数 =1+2+4+8....2^(h) =2^(h+1)-1 .....(ii)

因此,插入:

树中的节点数 = 1 +(左子树中的节点数)+(右子树中的节点数)

=> N = 1 + (2^(h+2)-1) + (2^(h+1)-1)

=> N = 1 + 3*(2^(h+1)) - 2

=> N = 3*(2^(h+1)) -1

=> 2^(h+1) = (N + 1)/3

将这个值代入方程 (i),我们得到:

Number of nodes in Left Subtree = 2^(h+2)-1 = 2*(N+1)/3 -1 =(2N-1)/3 < (2N/3)

因此,对于具有 N 个节点的树,子树中最大节点数的上限为 2N/3。

【讨论】:

我还是不明白。是不是就算满了也不会发生,为什么一定要半满。有人解释一下 - 我很困惑。 @SundarRajan check math.stackexchange.com/questions/181022/… 特别是This is the most the heap can get imbalanced; adding another node will either begin to rebalance the heap (by filling out the other, right, half of the last level) or break the heap's shape property of being a complete binary tree部分 很好的解释。【参考方案3】:

对于高度为h 的完全二叉树,节点数为f(h) = 2^h - 1。在上述情况下,我们有几乎完整的二叉树,下半部分已满。我们可以将其可视化为root + left complete tree + right complete tree 的集合。如果原始树的高度是h,那么左边的高度是h - 1,右边的高度是h - 2。所以方程变成了

n = 1 + f(h-1) + f(h-2)(1)

我们想解决上面的f(h-1) 表示为n

f(h-2) = 2^(h-2) - 1 = (2^(h-1)-1+1)/2 - 1 = (f(h-1) - 1)/2(2)

使用上面的(1)我们有

n = 1 + f(h-1) + (f(h-1) - 1)/2 = 1/2 + 3*f(h-1)/2

=> f(h-1) = 2*(n-1/2)/3

因此 O(2n/3)

【讨论】:

不是f(h) = 2^(h+1) - 1吗? 优秀的答案。请更正@afnrf 提到的 f(h)【参考方案4】:

添加到 swen 的答案。当 k 趋于无穷时,(2k + 1) / (3k + 2) 如何趋于 2 / 3,

Lim_(k -> inf) (2k + 1) / (3k + 2) = Lim_(k -> inf) k(2 + 1 / k) / k(3 + 2 / k) = Lim_(k -> inf) (2 + 1 / k) / (3 + 2 / k)

应用限制,你得到 2/3

【讨论】:

【参考方案5】:

节点数 -

0 级,即根为 2^0 1 级为 2^1 2 级为 2^2 ... 第n级为2^n

从0级到n级所有节点的总和,

S = 2^0 + 2^1 + 2^2 + ... + 2^n

从几何级数求和规则我们知道

x^0 + x^1 + x^2 + ... + x^(n) = (x^(n+1) - 1)/(x-1)

代入x = 2,我们得到

S = 2^(n+1) - 1。即 2^(n+1) = S + 1

由于 2^(n+1) 是第 n+1 层的节点总数,因此我们可以说具有 0 个子节点的节点数比具有 2 个子节点的节点数多 1。

现在让我们计算左子树、右树和总节点的数量..

假设根的左子树中的非叶节点数 = k。

由上述推理,左子树的叶子节点数或 根 = k + 1。 root = k 的右子树中的非叶节点数,因为该树被称为恰好是半满的。

根的左子树的节点总数 = k + k + 1 = 2k +

树中的节点总数,n = (2k + 1) + k + 1 = 3k + 2。 左子树中的节点与总节点的比率 = (2k + 1) / (3k + 2) 以 2/3 为界。

这就是说每个孩子的子树的大小最多为 2n/3 的原因。

【讨论】:

以上是关于Max-Heapify 中最坏的情况——你如何得到 2n/3?的主要内容,如果未能解决你的问题,请参考以下文章

MAX_HEAPIFY 算法和最坏情况的递归关系

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

为啥 HashMap 调整大小以防发生碰撞或最坏的情况

# Java 面试题总结

analysis of algorithms

阿里电话面试