-
Notifications
You must be signed in to change notification settings - Fork 13
/
Binary_Heap.py
143 lines (124 loc) · 5.41 KB
/
Binary_Heap.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
class Heap: # time - O(1) space-O(N)
def __init__(self, size):
self.customList = (size+1) * [None]
self.heapSize = 0
self.maxSize = size + 1
'''PEEKING IN BINARY HEAP'''
def peekHeap(rootNode): # time - O(1) space-O(1)
if not rootNode:
return
else:
return rootNode.customList[1]
'''SIZE OF BINARY HEAP'''
def sizeofHeap(rootNode): # time - O(1) space-O(1)
if not rootNode:
return
else:
return rootNode.heapSize
'''TRAVERSAL IN BINARY HEAP'''
def levelOrderTraversal(rootNode): # time - O(N) space-O(1)
if not rootNode:
return
else:
for i in range(1, rootNode.heapSize + 1):
print(rootNode.customList[i])
'''INSERTION IN BINARY HEAP'''
#helper function heapify to maintain properties of the binary heap during insertion
def heapify_toInsert(rootNode, idx, heapType): # time - O(logN) space-O(logN)
parent_idx = int(idx / 2) #left = 2x, right= 2x+ 1, hence root = x, so 2x/2= x, hence we divide idx/2 to fetch parent
if idx <= 1: #since we skip 0th index for faster calc
return
if heapType == "Min":
#check if curr node is < than its parents
if rootNode.customList[idx] < rootNode.customList[parent_idx]:
temp = rootNode.customList[idx]
rootNode.customList[idx] = rootNode.customList[parent_idx]
rootNode.customList[parent_idx] = temp
heapify_toInsert(rootNode, parent_idx, heapType)
elif heapType == "Max":
#check if curr node is > than its parents
if rootNode.customList[idx] > rootNode.customList[parent_idx]:
temp = rootNode.customList[idx]
rootNode.customList[idx] = rootNode.customList[parent_idx]
rootNode.customList[parent_idx] = temp
heapify_toInsert(rootNode, parent_idx, heapType)
def insertNode(rootNode, nodeValue, heapType): # time - O(logN) space-O(logN)
if rootNode.heapSize + 1 == rootNode.maxSize:
return "The Binary Heap is full!"
rootNode.customList[rootNode.heapSize + 1] = nodeValue
rootNode.heapSize += 1
heapify_toInsert(rootNode, rootNode.heapSize, heapType)
return "The value has been successfully inserted to the binary heap!"
'''EXTRACTION IN BINARY HEAP'''
#helper function heapify to maintain properties of the binary heap during extraction
def heapify_toExtract(rootNode, idx, heapType):
leftIdx = idx * 2
rightIdx = idx * 2 + 1
swapChild = 0
# 1st condition - check if heapsize is less than leftidx
if rootNode.heapSize < leftIdx:
return
# 2nd condition - check if heapsize is equal to leftidx and do adjustments(swap) for min & max heap
elif rootNode.heapSize == leftIdx:
if heapType == "Min":
if rootNode.customList[idx] > rootNode.customList[leftIdx]:
#swap
temp = rootNode.customList[idx]
rootNode.customList[idx] = rootNode.customList[leftIdx]
rootNode.customList[leftIdx] = temp
return
else: # condition for max heap
if rootNode.customList[idx] < rootNode.customList[leftIdx]:
#swap
temp = rootNode.customList[idx]
rootNode.customList[idx] = rootNode.customList[leftIdx]
rootNode.customList[leftIdx] = temp
return
# 3rd condition - check if there are left as well as right child, then take least element
# among them for min, and max element for max
else:
if heapType == "Min":
#find smallest child
if rootNode.customList[leftIdx] < rootNode.customList[rightIdx]:
swapChild = leftIdx
else:
swapChild = rightIdx
# replace it with parent node
if rootNode.customList[idx] > rootNode.customList[swapChild]:
#swap
temp = rootNode.customList[idx]
rootNode.customList[idx] = rootNode.customList[swapChild]
rootNode.customList[swapChild] = temp
else:
#find biggest child
if rootNode.customList[leftIdx] > rootNode.customList[rightIdx]:
swapChild = leftIdx
else:
swapChild = rightIdx
if rootNode.customList[idx] < rootNode.customList[swapChild]:
#swap
temp = rootNode.customList[idx]
rootNode.customList[idx] = rootNode.customList[swapChild]
rootNode.customList[swapChild] = temp
heapify_toExtract(rootNode, swapChild, heapType)
# replace it with parent node
def extractNode(rootNode, heapType): # time - O(logN) space-O(logN)
if rootNode.heapSize == 0:
return
else:
extractedNode = rootNode.customList[1]
rootNode.customList[1] = rootNode.customList[rootNode.heapSize]
rootNode.customList[rootNode.heapSize] = None
rootNode.heapSize -= 1
heapify_toExtract(rootNode, 1, heapType)
return extractedNode
def deleteEntireBinaryHeap(rootNode):
rootNode.customList = None
newBinaryHeap = Heap(5)
#print(sizeofHeap(newBinaryHeap))
insertNode(newBinaryHeap, 6 , "Max")
insertNode(newBinaryHeap, 9 , "Max")
insertNode(newBinaryHeap, 5 , "Max")
insertNode(newBinaryHeap, 10 , "Max")
extractNode(newBinaryHeap, "Max")
levelOrderTraversal(newBinaryHeap)