1+ """
2+ Max-heap
3+
4+ Author: Wenru Dong
5+ """
6+
7+ from typing import Optional , List
8+
9+ class Heap :
10+ def __init__ (self , capacity : int ):
11+ self ._data = [0 ] * (capacity + 1 )
12+ self ._capacity = capacity
13+ self ._count = 0
14+
15+ @classmethod
16+ def _parent (cls , child_index : int ) -> int :
17+ """The parent index."""
18+ return child_index // 2
19+
20+ @classmethod
21+ def _left (cls , parent_index : int ) -> int :
22+ """The left child index."""
23+ return 2 * parent_index
24+
25+ @classmethod
26+ def _right (cls , parent_index : int ) -> int :
27+ """The right child index."""
28+ return 2 * parent_index + 1
29+
30+ def _siftup (self ) -> None :
31+ i , parent = self ._count , Heap ._parent (self ._count )
32+ while parent and self ._data [i ] > self ._data [parent ]:
33+ self ._data [i ], self ._data [parent ] = self ._data [parent ], self ._data [i ]
34+ i , parent = parent , Heap ._parent (parent )
35+
36+ @classmethod
37+ def _siftdown (cls , a : List [int ], count : int , root_index : int = 1 ) -> None :
38+ i = larger_child_index = root_index
39+ while True :
40+ left , right = cls ._left (i ), cls ._right (i )
41+ if left <= count and a [i ] < a [left ]:
42+ larger_child_index = left
43+ if right <= count and a [larger_child_index ] < a [right ]:
44+ larger_child_index = right
45+ if larger_child_index == i : break
46+ a [i ], a [larger_child_index ] = a [larger_child_index ], a [i ]
47+ i = larger_child_index
48+
49+ def insert (self , value : int ) -> None :
50+ if self ._count >= self ._capacity : return
51+ self ._count += 1
52+ self ._data [self ._count ] = value
53+ self ._siftup ()
54+
55+ def remove_max (self ) -> Optional [int ]:
56+ if self ._count :
57+ result = self ._data [1 ]
58+ self ._data [1 ] = self ._data [self ._count ]
59+ self ._count -= 1
60+ Heap ._siftdown (self ._data , self ._count )
61+ return result
62+
63+ @classmethod
64+ def build_heap (cls , a : List [int ]) -> None :
65+ """Data in a needs to start from index 1."""
66+ for i in range ((len (a ) - 1 )// 2 , 0 , - 1 ):
67+ cls ._siftdown (a , len (a ) - 1 , i )
68+
69+ @classmethod
70+ def sort (cls , a : List [int ]) -> None :
71+ """Data in a needs to start from index 1."""
72+ cls .build_heap (a )
73+ k = len (a ) - 1
74+ while k > 1 :
75+ a [1 ], a [k ] = a [k ], a [1 ]
76+ k -= 1
77+ cls ._siftdown (a , k )
78+
79+ def __repr__ (self ):
80+ return self ._data [1 : self ._count + 1 ].__repr__ ()
81+
82+
83+ if __name__ == "__main__" :
84+ hp = Heap (10 )
85+ hp .insert (3 )
86+ hp .insert (9 )
87+ hp .insert (1 )
88+ hp .insert (8 )
89+ hp .insert (7 )
90+ hp .insert (3 )
91+ print (hp )
92+ for _ in range (6 ):
93+ print (hp .remove_max ())
94+ a = [0 , 6 , 3 , 4 , 0 , 9 , 2 , 7 , 5 , - 2 , 8 , 1 , 6 , 10 ]
95+ Heap .sort (a )
96+ print (a [1 :])
0 commit comments