是否有O(n)算法来构建最大堆?

时间:2009-11-24 01:33:27

标签: algorithm

给定一个数组,是否有O(n)算法来构建最大堆?

5 个答案:

答案 0 :(得分:22)

是的,就像在这段代码中一样:

for (int i = N/2; i >= 0; --i)
    push_heap(heap + i, N - i);

push_heap是一个函数,它接受指向堆和堆大小的指针并推送堆顶部,直到遵守堆条件或节点到达堆的底部。)

要了解这是O(N)的原因,请查看完整的二叉树:

  • 1/2元素(最后一级,i> N / 2)被按下最多0步 - > N / 2 * 0操作
  • 1/4元素(最后-1级,i> N / 4)最多下推1步 - > N / 4 * 1操作
  • 1/8个元素(最后2个级别,i> N / 8)被按下最多2个步骤 - > N / 8 * 2操作 ...

      N/4 * 1 + N/8 * 2 + N/16 * 3 + ... =
    
      N/4 * 1 + N/8 * 1 + N/16 * 1 + ... +
                N/8 * 1 + N/16 * 2 + ... =
    
      N/4 * 1 + N/8 * 1 + N/16 * 1 + ... +    // < N/2
                N/8 * 1 + N/16 * 1 + ... +    // < N/4
                          N/16 * 1 + ... +    // < N/8
                                     ... =    // N/2 + N/4 + N/8 + ... < N
    

希望数学不是太复杂。如果你在树上查看并添加每个节点可以向下推的程度,你会看到上限O(N)。

答案 1 :(得分:5)

是的,有:Building a heap

答案 2 :(得分:0)

提示:假设您使用的是任意二叉树而不是数组。您能想到一种有效的方法来修复任何不满足堆属性的节点吗?

答案 3 :(得分:-1)

如果您使用Fibonacci Heap,则会获得amortized O(1)插入。因此,您可以从数组中以摊销的O(n)构建最大堆。

执行此类,我将其作为练习*。

*虽然,维基百科页面上有链接的示例实现。

答案 4 :(得分:-4)

我不这么认为。我认为你能做的最好的事情就是O(log n),或者用像fib堆这样的东西做得更好。