built-in max heap API in Python

前端 未结 2 1861
一向
一向 2021-02-03 22:50

Default heapq is min queue implementation and wondering if there is an option for max queue? Thanks.

I tried the solution using _heapify_max for max heap, but how to han

相关标签:
2条回答
  • 2021-02-03 22:57

    In the past I have simply used sortedcontainers's SortedList for this, as:

    > a = SortedList()
    > a.add(3)
    > a.add(2)
    > a.add(1)
    > a.pop()
    3
    

    It's not a heap, but it's fast and works directly as required.

    If you absolutely need it to be a heap, you could make a general negation class to hold your items.

    class Neg():
        def __init__(self, x):
            self.x = x
    
        def __cmp__(self, other):
            return -cmp(self.x, other.x)
    
    def maxheappush(heap, item):
        heapq.heappush(heap, Neg(item))
    
    def maxheappop(heap):
        return heapq.heappop(heap).x
    

    But that will be using a little more memory.

    0 讨论(0)
  • 2021-02-03 23:11

    There is a _heappop_max function in the latest cpython source that you may find useful:

    def _heappop_max(heap):
        """Maxheap version of a heappop."""
        lastelt = heap.pop()    # raises appropriate IndexError if heap is empty
        if heap:
            returnitem = heap[0]
            heap[0] = lastelt
            heapq._siftup_max(heap, 0)
            return returnitem
        return lastelt
    

    If you change the heappush logic using heapq._siftdown_max you should get the desired output:

    def _heappush_max(heap, item):
        heap.append(item)
        heapq._siftdown_max(heap, 0, len(heap)-1)
    
    
    def _heappop_max(heap):
        """Maxheap version of a heappop."""
        lastelt = heap.pop()  # raises appropriate IndexError if heap is empty
        if heap:
            returnitem = heap[0]
            heap[0] = lastelt
            heapq._siftup_max(heap, 0)
            return returnitem
        return lastelt
    
    
    def heapsort2(iterable):
        h = []
        heapq._heapify_max(h)
        for value in iterable:
            _heappush_max(h, value)
        return [_heappop_max(h) for i in range(len(h))]
    

    Output:

    In [14]: heapsort2([1,3,6,2,7,9,0,4,5,8])
    Out[14]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    
    In [15]: heapsort2([7, 8, 9, 6, 4, 2, 3, 5, 1, 0])
    Out[15]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    
    In [16]: heapsort2([19,13,15,17,11,10,14,20,18])
    Out[16]: [20, 19, 18, 17, 15, 14, 13, 11, 10]
    
    In [17]: heapsort2(["foo","bar","foobar","baz"])
    Out[17]: ['foobar', 'foo', 'baz', 'bar']
    
    0 讨论(0)
提交回复
热议问题