Search code examples
pythonpython-3.xmin-heapmax-heap

Min/Max Heap implementation in Python


This is my implementation of a MinHeap and MaxHeap in python. This uses a comparator to reverse the sequence of storage in the MaxHeap

import heapq


class MinHeap:
    def __init__(self):
        self.heap = []

    def push(self, item):
        heapq.heappush(self.heap, item)

    def pop(self):
        return heapq.heappop(self.heap)

    def peek(self):
        return self.heap[0]

    def __getitem__(self, item):
        return self.heap[item]

    def __len__(self):
        return len(self.heap)


class MaxHeap(MinHeap):
    def push(self, item):
        heapq.heappush(self.heap, Comparator(item))

    def pop(self):
        return heapq.heappop(self.heap)

    def peek(self):
        return self.heap[0]

    def __getitem__(self, i):
        return self.heap[i].val


class Comparator:
    def __init__(self, val):
        self.val = val

    def __lt__(self, other):
        return self.val > other

    def __eq__(self, other):
        return self.val == other




if __name__ == '__main__':
    max_heap = MaxHeap()
    max_heap.push(12)
    max_heap.push(3)
    max_heap.push(17)
    print(max_heap.pop())

The MinHeap seems to work fine, however the MaxHeap throw up the following error.

<__main__.Comparator object at 0x10a5c1080>

I don't quite seem to understand what am I doing wrong here. Can someone help me with this.


Solution

  • I've added __repr__ and __gt__ methods to your Comparator class, so the code now runs, and the Comparator instances display their val when printed.

    The important thing is to get those comparison methods to do the comparisons correctly between two Comparator instances.

    You'll notice that I've eliminated most of the methods from MaxHeap. They aren't needed because the methods inherited from MinHeap work ok. You may wish to restore this one to MaxHeap

    def __getitem__(self, i):
        return self.heap[i].val
    

    depending on how you intend to use MaxHeap.

    import heapq
    
    class MinHeap:
        def __init__(self):
            self.heap = []
    
        def push(self, item):
            heapq.heappush(self.heap, item)
    
        def pop(self):
            return heapq.heappop(self.heap)
    
        def peek(self):
            return self.heap[0]
    
        def __getitem__(self, item):
            return self.heap[item]
    
        def __len__(self):
            return len(self.heap)
    
    class MaxHeap(MinHeap):
        def push(self, item):
            heapq.heappush(self.heap, Comparator(item))
    
    class Comparator:
        def __init__(self, val):
            self.val = val
    
        def __lt__(self, other):
            return self.val > other.val
    
        def __eq__(self, other):
            return self.val == other.val
    
        def __repr__(self):
            return repr(self.val)
    
    if __name__ == '__main__':
        max_heap = MaxHeap()
        max_heap.push(12)
        max_heap.push(3)
        max_heap.push(17)
    
        while True:
            try:
                print(max_heap.pop())
            except IndexError:
                # The heap's empty, bail out
                break
    

    output

    17
    12
    3
    

    It's probably a Good Idea to give Comparator the full set of rich comparison methods. They aren't needed to make the above code work, but they will make the Comparator instances more flexible. So in case you want them, here they are:

    def __lt__(self, other):
        return self.val > other.val
    
    def __le__(self, other):
        return self.val >= other.val
    
    def __gt__(self, other):
        return self.val < other.val
    
    def __ge__(self, other):
        return self.val <= other.val
    
    def __eq__(self, other):
        return self.val == other.val
    
    def __ne__(self, other):
        return self.val != other.val