Why is heapify linear?

Tim Peters tim.peters at gmail.com
Mon Nov 1 19:45:24 EST 2004


[Scott David Daniels]
> I am sorry, but in the Python 2.4 description of "heapify", I find the
> description of "Transform list x into a heap, in-place, in linear time,"
> unbelievable.  I understand the hand-wave that makes dictionary building
> linear (though I have a hard time with even that).  Could somebody tell
> me what twist of logic makes "heapify" linear, except in the sense that
> linear is coming to mean "very fast?"

There are no hands waving.  Dict-building is best-case and
expected-case linear time, but worst-case quadratic time.  For
heapification, all three are linear.  That's all rigorously provable
(and typically are so proved in a first course on algorithmic
complexity).  Google on

    heapify linear

to find proofs for heapification bounds.  But you perhaps won't
*believe* it until you can't deny it <wink>.  So try it:

"""
class CmpCounter:
    def __init__(self, i):
        self.i = i

    def __cmp__(self, other):
        global cmpcount
        cmpcount += 1
        return cmp(self.i, other.i)

from heapq import heapify
import random
n = 10000

xs = [CmpCounter(i) for i in range(n)]

def tryone(tag, xs):
    global cmpcount
    cmpcount = 0
    heapify(xs)
    print tag, "len", len(xs), "# comparisions", cmpcount

for i in range(10):
    random.shuffle(xs)
    tryone("random", xs)

xs.sort()
tryone("already sorted", xs)

xs.sort(reverse=True) # using 2.4b1 here
tryone("reverse sorted", xs)
"""

"Already sorted" is essentially the worst case for min-heap
heapification (each new element added is then the smallest seen so
far, and has to bubble all the way from the bottom of the heap-so-far
to the new root location).

Note that "the obvious" way to transform a list into a heap is not
worst-case linear time.  Linear-time heapification is due to Floyd. 
Someone should patent it <wink>.



More information about the Python-list mailing list