-
Notifications
You must be signed in to change notification settings - Fork 0
/
heap(minheap).py
110 lines (83 loc) · 3.35 KB
/
heap(minheap).py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
class Heap:
def __init__(self, initial_size=10):
self.cbt = [None for _ in range(initial_size)] # initialize arrays
self.next_index = 0 # denotes next index where new element should go
def insert(self, data):
# insert element at the next index
self.cbt[self.next_index] = data
# heapify
self._up_heapify()
# increase index by 1
self.next_index += 1
# double the array and copy elements if next_index goes out of array bounds
if self.next_index >= len(self.cbt):
temp = self.cbt
self.cbt = [None for _ in range(2 * len(self.cbt))]
for index in range(self.next_index):
self.cbt[index] = temp[index]
def remove(self):
if self.size() == 0:
return None
self.next_index -= 1
to_remove = self.cbt[0]
last_element = self.cbt[self.next_index]
# place last element of the cbt at the root
self.cbt[0] = last_element
# we do not remove the elementm, rather we allow next `insert` operation to overwrite it
self.cbt[self.next_index] = to_remove
self._down_heapify()
return to_remove
def size(self):
return self.next_index
def is_empty(self):
return self.size() == 0
def _up_heapify(self):
# print("inside heapify")
child_index = self.next_index
while child_index >= 1:
parent_index = (child_index - 1) // 2
parent_element = self.cbt[parent_index]
child_element = self.cbt[child_index]
if parent_element > child_element:
self.cbt[parent_index] = child_element
self.cbt[child_index] = parent_element
child_index = parent_index
else:
break
def _down_heapify(self):
parent_index = 0
while parent_index < self.next_index:
left_child_index = 2 * parent_index + 1
right_child_index = 2 * parent_index + 2
parent = self.cbt[parent_index]
left_child = None
right_child = None
min_element = parent
# check if left child exists
if left_child_index < self.next_index:
left_child = self.cbt[left_child_index]
# check if right child exists
if right_child_index < self.next_index:
right_child = self.cbt[right_child_index]
# compare with left child
if left_child is not None:
min_element = min(parent, left_child)
# compare with right child
if right_child is not None:
min_element = min(right_child, min_element)
# check if parent is rightly placed
if min_element == parent:
return
if min_element == left_child:
self.cbt[left_child_index] = parent
self.cbt[parent_index] = min_element
parent = left_child_index
elif min_element == right_child:
self.cbt[right_child_index] = parent
self.cbt[parent_index] = min_element
parent = right_child_index
def get_minimum(self):
# Returns the minimum element present in the heap
if self.size() == 0:
return None
return self.cbt[0]