how to use "heapq" module as a max-heap?

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sun Mar 29 05:25:05 EDT 2009


(Top posting and incorrect quoting corrected.)

On Sun, 29 Mar 2009 16:48:53 +0800, apollo wrote:
 
> > as we all known, in the standard module 'heapq',  we can easily get
> > the smallest item from the heap. i.e. it's an implementation of 
> > min-heap.
> > 
> > my question is how to use 'heapq' to extract the biggest item from the
> > heap? is it possible?
> > 
> > thanks  in advance.:)
>
> if the 'heapq' module supports user-defined comparasion, this problem
> will be much easier.



It certain does. Here's one way of turning the min-heap into a fake max-
heap:

>>> class Backwards(float):
...     def __lt__(self, other):
...             return not float.__le__(self, other)
...     def __le__(self, other):
...             return not float.__lt__(self, other)
...     def __gt__(self, other):
...             return not float.__ge__(self, other)
...     def __ge__(self, other):
...             return not float.__gt__(self, other)
...
>>> x, y = Backwards(27), Backwards(1270)
>>> x > y
True
>>> y < x
True
>>> heap = []
>>> for x in xrange(20):
...     heapq.heappush(heap, Backwards(x))
...
>>> heapq.heappop(heap)
19.0
>>> heapq.heappop(heap)
18.0
>>> heap
[17.0, 16.0, 13.0, 15.0, 8.0, 10.0, 12.0, 9.0, 14.0, 2.0, 7.0, 1.0, 5.0, 
4.0, 11.0, 0.0, 6.0, 3.0]

The problem with this approach is that when you pop the "largest" item, 
and compare it to something else, it will compare *smaller* because of 
the custom comparisons, so now you have to remove the custom comparisons 
to revert to the standard behaviour. The book-keeping for this could be 
awful.


However, another approach is to use the nlargest function:


>>> heap = []
>>> for i in (5, 6, 7, 0, 1, 10, 2, 4, 3, 9, 8):
...     heapq.heappush(heap, i)
...
>>> heap
[0, 1, 2, 3, 5, 10, 7, 6, 4, 9, 8]
>>> heapq.nlargest(1, heap)
[10]


The problem with this is that the value is not popped off the heap. Also, 
I'm not sure how efficient nlargest is.



-- 
Steven



More information about the Python-list mailing list