开发者

How is make_heap in C++ implemented to have complexity of 3N?

I wonder what's the algorithm of make_heap in in C++ such that the complexity is 3*N? Only way I can th开发者_如何转开发ink of to make a heap by inserting elements have complexity of O(N Log N). Thanks a lot!


You represent the heap as an array. The two elements below the i'th element are at positions 2i+1 and 2i+2. If the array has n elements then, starting from the end, take each element, and let it "fall" to the right place in the heap. This is O(n) to run.

Why? Well for n/2 of the elements there are no children. For n/4 there is a subtree of height 1. For n/8 there is a subtree of height 2. For n/16 a subtree of height 3. And so on. So we get the series n/22 + 2n/23 + 3n/24 + ... = (n/2)(1 * (1/2 + 1/4 + 1/8 + . ...) + (1/2) * (1/2 + 1/4 + 1/8 + . ...) + (1/4) * (1/2 + 1/4 + 1/8 + . ...) + ...) = (n/2) * (1 * 1 + (1/2) * 1 + (1/4) * 1 + ...) = (n/2) * 2 = n. Or, formatted maybe more readably to see the geometric series that are being summed:

n/2^2 + 2n/2^3 + 3n/2^4 + ...
  = (n/2^2 +  n/2^3 +  n/2^4 + ...)
           + (n/2^3 +  n/2^4 + ...)
                    + (n/2^4 + ...)
    + ...
  = n/2^2 (1 + 1/2 + 1/2^4 + ...)
           + n/2^3 (1 + 1/2 + 1/2^3 + ...)
                    + n/2^4 (1 + 1/2 + 1/2^3 + ...)
    + ...
  = n/2^2 * 2
           + n/2^3 * 2
                    + n/2^4 * 2
    + ...
  = n/2 + n/2^2 + n/2^3 + ...
  = n(1/2 + 1/4 + 1/8 + ...)
  = n

And the trick we used repeatedly is that we can sum the geometric series with

1 + 1/2 + 1/4 + 1/8 + ...
   = (1 + 1/2 + 1/4 + 1/8 + ...) (1 - 1/2)/(1 - 1/2)
   = (1 * (1 - 1/2)
        + 1/2 * (1 - 1/2)
              + 1/4 * (1 - 1/2)
                    + 1/8 * (1 - 1/2)
                          + ...) / (1 - 1/2)
   = (1 - 1/2
        + 1/2 - 1/4
              + 1/4 - 1/8
                    + 1/8 - 1/16
                          + ...) / (1 - 1/2)
   = 1 / (1 - 1/2)
   = 1 / (1/2)
   = 2

So the total number of "see if I need to fall one more, and if so which way do I fall? comparisons comes to n. But you get round-off from discretization, so you always come out to less than n sets of swaps to figure out. Each of which requires at most 3 comparisons. (Compare root to each child to see if it needs to fall, then the children to each other if the root was larger than both children.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜