362

Python includes the heapq module for min-heaps, but I need a max heap. What should I use for a max-heap implementation in Python?

Daniel Stutzbach
  • 70,140
  • 17
  • 84
  • 76
Douglas Mayle
  • 19,815
  • 8
  • 41
  • 57

19 Answers19

389

The easiest way is to invert the value of the keys and use heapq. For example, turn 1000.0 into -1000.0 and 5.0 into -5.0.

Daniel Stutzbach
  • 70,140
  • 17
  • 84
  • 76
  • 56
    It's also the standard solution. – Andrew McGregor Mar 23 '10 at 16:30
  • 77
    uggh; total kludge. I am surprised `heapq` does not provide a reverse. – shabbychef Apr 17 '10 at 00:33
  • 62
    Wow. I'm *amazed* that this is not provided by `heapq`, and that there is no good alternative. – ire_and_curses Jun 10 '10 at 17:46
  • 2
    yeah, inverting doesn't help if you don't have `int` / `float`'s... in fact, there really doesn't need to be any sensible inverse for an order in general (take, for instance, something isomorphic to the natural numbers). – gatoatigrado Jun 29 '12 at 00:28
  • 28
    @gatoatigrado: If you have something that doesn't easily map to `int`/`float`, you can invert the ordering by wrapping them in a class with an inverted `__lt__` operator. – Daniel Stutzbach Jul 23 '12 at 14:05
  • 8
    And what if you have a mix of positive and negative numbers to begin with? Then what? – temporary_user_name Nov 29 '13 at 10:04
  • 9
    @Aerovistae same advice applies: invert the values (i.e. switch the sign) regardless if positive or negative to begin with. – Dennis Mar 13 '14 at 23:49
  • [nneonneo's answer](http://stackoverflow.com/a/12682153/4116239) to a duplicate question provides a complete example of @DanielStutzbach's alternate solution: a wrapper class that reverses the total ordering of the contained class. – Kevin J. Chase Oct 18 '15 at 05:09
  • Well, this solution looks painstaking at first. But after implementation, it is actually pretty slick, with minimal code changed. –  Mar 05 '16 at 02:21
  • Poke. See my answer based on yours. – noɥʇʎԀʎzɐɹƆ Jun 11 '16 at 14:56
  • Here's an example showing that @DanielStutzbach 's method works https://gist.github.com/jtara1/574e87ffa1b49ac09a892aad1620f2f7 – James T. Sep 17 '17 at 22:36
  • 7
    this is ugly, and how do you invert `string`? – boh Dec 10 '17 at 18:05
  • @boh your best bet is to `import` the private maxheap methods from `heapq` and implement `heappush_max()` yourself using those methods. Or create your own wrapper class around strings such at `heapify()` creates a maxheap for your custom string types. – Flair Mar 03 '20 at 04:12
334

You can use

import heapq
listForTree = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]    
heapq.heapify(listForTree)             # for a min heap
heapq._heapify_max(listForTree)        # for a maxheap!!

If you then want to pop elements, use:

heapq.heappop(minheap)      # pop from minheap
heapq._heappop_max(maxheap) # pop from maxheap
oerpli
  • 340
  • 3
  • 16
Lijo Joseph
  • 3,793
  • 1
  • 12
  • 12
  • 53
    Looks like there are some undocumented functions for max heap: `_heapify_max`, `_heappushpop_max`, `_siftdown_max`, and `_siftup_max`. – Ziyuan Aug 07 '14 at 13:35
  • 184
    Wow. I'm *amazed* that there *IS* such a built-in solution in heapq. But then it is totally *unreasonable* that it is *NOT* even slightly mentioned at all in the official document! WTF! – RayLuo Apr 21 '15 at 06:48
  • 3
    Somehow I can't find this in Python Python 2.7.3. – Heberto Mayorquin Aug 23 '15 at 08:32
  • 4
    Hi Lijo, looks like _heapify_max not working for dyanamically added/removed elements? See my code from => http://stackoverflow.com/questions/33024215/built-in-max-heap-api-in-python, your insights are appreciated. Thanks. :) – Lin Ma Oct 08 '15 at 22:25
  • 49
    Any of the pop/push functions break the max heap structure, so this method is not feasible. – Siddhartha Jul 08 '17 at 06:21
  • 40
    DO NOT USE IT. As LinMa and Siddhartha noticed, push/pop breaks the order. – Alex Fedulov Aug 19 '17 at 16:29
  • 5
    You can use it as long as you don't push new elements and use `_heappop_max`to pop them – oerpli Feb 13 '18 at 12:58
  • 9
    Just to state the obvious, `_heapify_max` etc. are private functions and therefore not part of the module's API. Use at your own risk, both with respect to functionality and forwards compatibility. – Sam Marinelli Sep 01 '18 at 05:25
  • 2
    @oerpli `._heappop_max` doesn't exist on my Python 2.7.15, only `._heappushpop_max` and `._heapify_max` for the underscore methods. Looks like the interface changed in Python 3 to include it. – Nimrod Oct 13 '18 at 06:19
  • 28
    The methods beginning with an underscore are **private** and can be **removed without prior notice**. Do not use them. – user4815162342 Jan 26 '19 at 08:47
  • 1
    Since they are private and can be removed without prior notice, you can just implement the methods yourself. – Flair Mar 03 '20 at 04:13
  • 3
    These private methods are built to support `heapq.nsmallest` and `heapq.merge` with `reverse=True`. – Escape0707 Apr 12 '20 at 09:15
  • @Siddhartha just use _heapify_max() after each push/pop then! – Shayan Amani Mar 16 '21 at 03:06
  • @oerpli is there inbuilt method to push element into a max-heap. I tried `heapq._heappush_max(heap, item)` but its not working. – Mahesh Nov 18 '21 at 07:41
  • @Mahesh You can look at the available methods here: https://github.com/python/cpython/blob/3.10/Lib/heapq.py – oerpli Nov 19 '21 at 11:57
127

The solution is to negate your values when you store them in the heap, or invert your object comparison like so:

import heapq

class MaxHeapObj(object):
  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 __str__(self): return str(self.val)

Example of a max-heap:

maxh = []
heapq.heappush(maxh, MaxHeapObj(x))
x = maxh[0].val  # fetch max value
x = heapq.heappop(maxh).val  # pop max value

But you have to remember to wrap and unwrap your values, which requires knowing if you are dealing with a min- or max-heap.

MinHeap, MaxHeap classes

Adding classes for MinHeap and MaxHeap objects can simplify your code:

class MinHeap(object):
  def __init__(self): self.h = []
  def heappush(self, x): heapq.heappush(self.h, x)
  def heappop(self): return heapq.heappop(self.h)
  def __getitem__(self, i): return self.h[i]
  def __len__(self): return len(self.h)

class MaxHeap(MinHeap):
  def heappush(self, x): heapq.heappush(self.h, MaxHeapObj(x))
  def heappop(self): return heapq.heappop(self.h).val
  def __getitem__(self, i): return self.h[i].val

Example usage:

minh = MinHeap()
maxh = MaxHeap()
# add some values
minh.heappush(12)
maxh.heappush(12)
minh.heappush(4)
maxh.heappush(4)
# fetch "top" values
print(minh[0], maxh[0])  # "4 12"
# fetch and remove "top" values
print(minh.heappop(), maxh.heappop())  # "4 12"
Isaac Turner
  • 2,398
  • 1
  • 24
  • 24
  • Nice. I've taken this and added an optional `list` parameter to \_\_init\_\_ in which case I call `heapq.heapify` and also added a `heapreplace` method. – Booboo Apr 30 '20 at 12:58
  • 2
    Surprised that no one caught this typo: MaxHeapInt --> MaxHeapObj. Otherwise, a very clean solution indeed. – Chiraz BenAbdelkader Jun 20 '20 at 07:44
  • Interestingly Fanchen Bao's answer to this question is very similar: https://stackoverflow.com/questions/8875706/heapq-with-custom-compare-predicate – Chiraz BenAbdelkader Jun 30 '20 at 17:45
  • Is this line needed? def __eq__(self, other): return self.val == other.val. I think it can also work without it. – apadana Oct 15 '20 at 16:59
  • @apadana Yes it is good to have - whether it is needed depends on the `heapify` implementation and what you want to do with your heap. We only need to define `__lt__` and `__eq__` to facilitate all comparisons between `MaxHeapObj` objects (, >=), which may be needed when e.g. searching your heap. – Isaac Turner Oct 20 '20 at 03:43
  • 1
    @ChirazBenAbdelkader Fanchen Bao's linked answer is using a tuple with a custom key object as first element, rather than using the custom object to wrap the elements, so slightly different. The tuple method allows passing a lambda which is cool. – Isaac Turner Oct 07 '21 at 20:54
55

The easiest and ideal solution

Multiply the values by -1

There you go. All the highest numbers are now the lowest and vice versa.

Just remember that when you pop an element to multiply it with -1 in order to get the original value again.

Sebastian Nielsen
  • 3,143
  • 4
  • 19
  • 35
  • 2
    Great, but most solution supports the classes/other types, and won't change actual data. The open question is if multiplying value by -1 won't change them (extremely precise float). – Alex Baranowski Jul 12 '19 at 20:08
  • 2
    @AlexBaranowski. That's true, but that has been the response from the maintainer: https://bugs.python.org/issue27295 – Flair Mar 03 '20 at 04:17
  • 1
    Well maintainers have their right not to implement some functionality, but this one IMO is actually useful. – Alex Baranowski Mar 03 '20 at 14:00
  • 1
    This could be a good solution for some coding round. Otherwise changing data within an application doesn't sound that great. – Adarsh Trivedi Aug 11 '20 at 18:56
17

The Easiest way is to convert every element into negative and it will solve your problem.

import heapq
heap = []
heapq.heappush(heap, 1*(-1))
heapq.heappush(heap, 10*(-1))
heapq.heappush(heap, 20*(-1))
print(heap)

The output will look like:

[-20, -1, -10]
Than Win Hline
  • 303
  • 2
  • 7
15

I implemented a max heap version of heapq and submitted it to PyPI. (Very slight change of heapq module CPython code.)

https://pypi.python.org/pypi/heapq_max/

https://github.com/he-zhe/heapq_max

Installation

pip install heapq_max

Usage

tl;dr: same as heapq module except adding ‘_max’ to all functions.

heap_max = []                           # creates an empty heap
heappush_max(heap_max, item)            # pushes a new item on the heap
item = heappop_max(heap_max)            # pops the largest item from the heap
item = heap_max[0]                      # largest item on the heap without popping it
heapify_max(x)                          # transforms list into a heap, in-place, in linear time
item = heapreplace_max(heap_max, item)  # pops and returns largest item, and
                                    # adds new item; the heap size is unchanged
Zhe He
  • 621
  • 6
  • 7
12

This is a simple MaxHeap implementation based on heapq. Though it only works with numeric values.

import heapq
from typing import List


class MaxHeap:
    def __init__(self):
        self.data = []

    def top(self):
        return -self.data[0]

    def push(self, val):
        heapq.heappush(self.data, -val)

    def pop(self):
        return -heapq.heappop(self.data)

Usage:

max_heap = MaxHeap()
max_heap.push(3)
max_heap.push(5)
max_heap.push(1)
print(max_heap.top())  # 5
Yuchen
  • 27,526
  • 21
  • 148
  • 215
11

I also needed to use a max-heap, and I was dealing with integers, so I just wrapped the two methods that I needed from heap as follows:

import heapq


def heappush(heap, item):
    return heapq.heappush(heap, -item)


def heappop(heap):
    return -heapq.heappop(heap)

And then I just replaced my heapq.heappush() and heapq.heappop() calls with heappush() and heappop() respectively.

Vikas Prasad
  • 2,861
  • 4
  • 26
  • 37
5

If you are inserting keys that are comparable but not int-like, you could potentially override the comparison operators on them (i.e. <= become > and > becomes <=). Otherwise, you can override heapq._siftup in the heapq module (it's all just Python code, in the end).

rlotun
  • 7,655
  • 4
  • 27
  • 22
  • 11
    “it's all just Python code”: it depends on your Python version and installation. For example, my installed heapq.py has some code after line 309 (`# If available, use C implementation`) that does exactly what the comment describes. – tzot Oct 17 '10 at 07:30
4

Extending the int class and overriding __lt__ is one of the ways.

import queue
class MyInt(int):
    def __lt__(self, other):
        return self > other

def main():
    q = queue.PriorityQueue()
    q.put(MyInt(10))
    q.put(MyInt(5))
    q.put(MyInt(1))
    while not q.empty():
        print (q.get())


if __name__ == "__main__":
    main()
Gaurav
  • 146
  • 4
  • It's possible, but I feel like it would slow things down a lot and use a lot of extra memory. MyInt can't really be used outside of the heap structure either. But thank you for typing up an example, it's interesting to see. – Leo Ufimtsev Jul 12 '19 at 14:21
  • Hah! One day after I commented I ran into the situation where I needed to put a custom object into a heap and needed a max heap. I actually re-googled this post and found your answer and based my solution off of it. (Custom object being a Point with x,y coordinate and __lt__ overriding comparing distance from center). Thank you for posting this, I upvoted! – Leo Ufimtsev Jul 13 '19 at 22:06
4

Best way:

from heapq import *
h = [5, 7, 9, 1, 3]
h_neg = [-i for i in h]
heapify(h_neg)            # heapify
heappush(h_neg, -2)       # push
print(-heappop(h_neg))    # pop
# 9
illuminato
  • 694
  • 1
  • 5
  • 21
3

Allowing you to chose an arbitrary amount of largest or smallest items

import heapq
heap = [23, 7, -4, 18, 23, 42, 37, 2, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
heapq.heapify(heap)
print(heapq.nlargest(3, heap))  # [42, 42, 37]
print(heapq.nsmallest(3, heap)) # [-4, -4, 2]
jasonleonhard
  • 8,968
  • 71
  • 54
1

I have created a heap wrapper that inverts the values to create a max-heap, as well as a wrapper class for a min-heap to make the library more OOP-like. Here is the gist. There are three classes; Heap (abstract class), HeapMin, and HeapMax.

Methods:

isempty() -> bool; obvious
getroot() -> int; returns min/max
push() -> None; equivalent to heapq.heappush
pop() -> int; equivalent to heapq.heappop
view_min()/view_max() -> int; alias for getroot()
pushpop() -> int; equivalent to heapq.pushpop
noɥʇʎԀʎzɐɹƆ
  • 8,421
  • 2
  • 44
  • 65
1

To elaborate on https://stackoverflow.com/a/59311063/1328979, here is a fully documented, annotated and tested Python 3 implementation for the general case.

from __future__ import annotations  # To allow "MinHeap.push -> MinHeap:"
from typing import Generic, List, Optional, TypeVar
from heapq import heapify, heappop, heappush, heapreplace


T = TypeVar('T')


class MinHeap(Generic[T]):
    '''
    MinHeap provides a nicer API around heapq's functionality.
    As it is a minimum heap, the first element of the heap is always the
    smallest.
    >>> h = MinHeap([3, 1, 4, 2])
    >>> h[0]
    1
    >>> h.peek()
    1
    >>> h.push(5)  # N.B.: the array isn't always fully sorted.
    [1, 2, 4, 3, 5]
    >>> h.pop()
    1
    >>> h.pop()
    2
    >>> h.pop()
    3
    >>> h.push(3).push(2)
    [2, 3, 4, 5]
    >>> h.replace(1)
    2
    >>> h
    [1, 3, 4, 5]
    '''
    def __init__(self, array: Optional[List[T]] = None):
        if array is None:
            array = []
        heapify(array)
        self.h = array
    def push(self, x: T) -> MinHeap:
        heappush(self.h, x)
        return self  # To allow chaining operations.
    def peek(self) -> T:
        return self.h[0]
    def pop(self) -> T:
        return heappop(self.h)
    def replace(self, x: T) -> T:
        return heapreplace(self.h, x)
    def __getitem__(self, i) -> T:
        return self.h[i]
    def __len__(self) -> int:
        return len(self.h)
    def __str__(self) -> str:
        return str(self.h)
    def __repr__(self) -> str:
        return str(self.h)


class Reverse(Generic[T]):
    '''
    Wrap around the provided object, reversing the comparison operators.
    >>> 1 < 2
    True
    >>> Reverse(1) < Reverse(2)
    False
    >>> Reverse(2) < Reverse(1)
    True
    >>> Reverse(1) <= Reverse(2)
    False
    >>> Reverse(2) <= Reverse(1)
    True
    >>> Reverse(2) <= Reverse(2)
    True
    >>> Reverse(1) == Reverse(1)
    True
    >>> Reverse(2) > Reverse(1)
    False
    >>> Reverse(1) > Reverse(2)
    True
    >>> Reverse(2) >= Reverse(1)
    False
    >>> Reverse(1) >= Reverse(2)
    True
    >>> Reverse(1)
    1
    '''
    def __init__(self, x: T) -> None:
        self.x = x
    def __lt__(self, other: Reverse) -> bool:
        return other.x.__lt__(self.x)
    def __le__(self, other: Reverse) -> bool:
        return other.x.__le__(self.x)
    def __eq__(self, other) -> bool:
        return self.x == other.x
    def __ne__(self, other: Reverse) -> bool:
        return other.x.__ne__(self.x)
    def __ge__(self, other: Reverse) -> bool:
        return other.x.__ge__(self.x)
    def __gt__(self, other: Reverse) -> bool:
        return other.x.__gt__(self.x)
    def __str__(self):
        return str(self.x)
    def __repr__(self):
        return str(self.x)


class MaxHeap(MinHeap):
    '''
    MaxHeap provides an implement of a maximum-heap, as heapq does not provide
    it. As it is a maximum heap, the first element of the heap is always the
    largest. It achieves this by wrapping around elements with Reverse,
    which reverses the comparison operations used by heapq.
    >>> h = MaxHeap([3, 1, 4, 2])
    >>> h[0]
    4
    >>> h.peek()
    4
    >>> h.push(5)  # N.B.: the array isn't always fully sorted.
    [5, 4, 3, 1, 2]
    >>> h.pop()
    5
    >>> h.pop()
    4
    >>> h.pop()
    3
    >>> h.pop()
    2
    >>> h.push(3).push(2).push(4)
    [4, 3, 2, 1]
    >>> h.replace(1)
    4
    >>> h
    [3, 1, 2, 1]
    '''
    def __init__(self, array: Optional[List[T]] = None):
        if array is not None:
            array = [Reverse(x) for x in array]  # Wrap with Reverse.
        super().__init__(array)
    def push(self, x: T) -> MaxHeap:
        super().push(Reverse(x))
        return self
    def peek(self) -> T:
        return super().peek().x
    def pop(self) -> T:
        return super().pop().x
    def replace(self, x: T) -> T:
        return super().replace(Reverse(x)).x


if __name__ == '__main__':
    import doctest
    doctest.testmod()

https://gist.github.com/marccarre/577a55850998da02af3d4b7b98152cf4

Marc Carré
  • 1,407
  • 13
  • 18
1

The heapq module has everything you need to implement a maxheap. It does only the heappush functionality of max-heap. I've demonstrated below how to overcome that below ⬇

Add this function in the heapq module:

def _heappush_max(heap, item):
    """Push item onto heap, maintaining the heap invariant."""
    heap.append(item)
    _siftdown_max(heap, 0, len(heap)-1)

and at the end add this :

try:
    from _heapq import _heappush_max
except ImportError:
    pass

Voila ! It's done.

PS - to go to heapq function . first write " import heapq" in your editor and then right click 'heapq' and select go to defintion.

Ritav Das
  • 11
  • 2
0

In case if you would like to get the largest K element using max heap, you can do the following trick:

nums= [3,2,1,5,6,4]
k = 2  #k being the kth largest element you want to get
heapq.heapify(nums) 
temp = heapq.nlargest(k, nums)
return temp[-1]
RowanX
  • 1,070
  • 2
  • 12
  • 26
  • 2
    Unfortunately, the time complexity for this is O(MlogM) where M = len(nums), which defeats the purpose of heapq. See the implementation and comments for `nlargest` here -> https://github.com/python/cpython/blob/7dc72b8d4f2c9d1eed20f314fd6425eab66cbc89/Lib/heapq.py#L521 – Arthur S Jan 04 '20 at 23:27
  • 1
    Thank you for your informative comment, will make sure to check the attached link. – RowanX Jan 06 '20 at 00:19
0

Following up to Isaac Turner's excellent answer, I'd like put an example based on K Closest Points to the Origin using max heap.

from math import sqrt
import heapq


class MaxHeapObj(object):
    def __init__(self, val):
        self.val = val.distance
        self.coordinates = val.coordinates

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

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

    def __str__(self):
        return str(self.val)


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

    def heappush(self, x):
        heapq.heappush(self.h, x)

    def heappop(self):
        return heapq.heappop(self.h)

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

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


class MaxHeap(MinHeap):
    def heappush(self, x):
        heapq.heappush(self.h, MaxHeapObj(x))

    def heappop(self):
        return heapq.heappop(self.h).val

    def peek(self):
        return heapq.nsmallest(1, self.h)[0].val

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


class Point():
    def __init__(self, x, y):
        self.distance = round(sqrt(x**2 + y**2), 3)
        self.coordinates = (x, y)


def find_k_closest(points, k):
    res = [Point(x, y) for (x, y) in points]
    maxh = MaxHeap()

    for i in range(k):
        maxh.heappush(res[i])

    for p in res[k:]:
        if p.distance < maxh.peek():
            maxh.heappop()
            maxh.heappush(p)

    res = [str(x.coordinates) for x in maxh.h]
    print(f"{k} closest points from origin : {', '.join(res)}")


points = [(10, 8), (-2, 4), (0, -2), (-1, 0), (3, 5), (-2, 3), (3, 2), (0, 1)]
find_k_closest(points, 3)
Apoorv Patne
  • 403
  • 3
  • 16
0

there's build in heap in python ,but I just want to share this if anyone want to build it by himself like me . I'm newbie in python don't judge if i made i mistake . algorithm is working but about the efficiency i don't know

class Heap :

    def __init__(self):
        self.heap = []
        self.size = 0


    def add(self, heap):
        self.heap = heap
        self.size = len(self.heap)

    def heappush(self, value):
        self.heap.append(value)
        self.size += 1


    def heapify(self, heap ,index=0):

        mid = int(self.size /2)
        """
            if you want to travel great value from bottom to the top you need to repeat swaping by the hight of the tree
            I  don't how how can i get the  height of the tree that's why i use sezi/2
            you can find height by this formula
            2^(x) = size+1  why 2^x because tree is growing exponentially 
            xln(2) = ln(size+1)
            x = ln(size+1)/ln(2)
        """

        for i in range(mid):
            self.createTee(heap ,index)

        return heap

    def createTee(self,  heap ,shiftindex):

        """
        """
        """

            this pos reffer to the index of the parent only parent with children
                    (1)
                (2)      (3)           here the size of list is 7/2 = 3
            (4)   (5)  (6)  (7)        the number of parent is 3 but we use {2,1,0} in while loop
                                       that why a put pos -1

        """
        pos = int(self.size /2 ) -1
        """
            this if you wanna sort this heap list we should swap max value in the root of the tree with the last
            value in the list and if you wanna repeat this until sort all list you will need to prevent the func from
            change what we already sorted I should decrease the size of the list that will heapify on it

        """

        newsize = self.size - shiftindex
        while pos >= 0 :
            left_child = pos * 2 + 1
            right_child = pos * 2 + 2
            # this mean that left child is exist
            if left_child < newsize:
                if right_child < newsize:
                    # if the right child exit we wanna check if left child > rightchild
                    # if right child doesn't exist we can check that we will get error out of range
                    if heap[pos] < heap[left_child] and heap[left_child]  > heap[right_child] :
                        heap[left_child] , heap[pos] = heap[pos], heap[left_child]
                # here if the righ child doesn't exist
                else:
                    if heap[pos] < heap[left_child] :
                        heap[left_child] , heap[pos] = heap[pos], heap[left_child]
            # if the right child exist
            if right_child < newsize :
                if heap[pos] < heap[right_child] :
                    heap[right_child], heap[pos] = heap[pos], heap[right_child]
            pos -= 1

        return heap

    def sort(self ):
        k = 1
        for i in range(self.size -1 ,0 ,-1):
            """
            because this is max heap we swap root with last element in the list

            """
            self.heap [0] , self.heap[i] = self.heap[i], self.heap[0]
            self.heapify(self.heap ,k)
            k+=1

        return self.heap


h = Heap()
h.add([5,7,0,8,9,10,20,30,50,-1] )
h.heappush(-2)
print(" before heapify ")
print(h.heap)
print(" after heapify ")
print(h.heapify(h.heap,0))
print(" after sort ")
print(h.sort())

Output :

before heapify [5, 7, 0, 8, 9, 10, 20, 30, 50, -1, -2]

after heapify [50, 30, 20, 8, 9, 10, 0, 7, 5, -1, -2]

after sort [-2, -1, 0, 5, 7, 8, 9, 10, 20, 30, 50]

I hope you understand my code . if there's something you don't understand put a comment I will try to help

Sar ibra
  • 7
  • 2
0
arr = [3,4,5,1,2,3,0,7,8,90,67,31,2,5,567]
# max-heap sort will lead the array to assending order
def maxheap(arr,p):
    
    for i in range(len(arr)-p):
        if i > 0:
            child = i
            parent = (i+1)//2 - 1
            
            while arr[child]> arr[parent] and child !=0:
                arr[child], arr[parent] = arr[parent], arr[child]
                child = parent
                parent = (parent+1)//2 -1
                
    
def heapsort(arr):
    for i in range(len(arr)):
        maxheap(arr,i)
        arr[0], arr[len(arr)-i-1]=arr[len(arr)-i-1],arr[0]
        
    return arr
        

print(heapsort(arr))

try this