Skip to content

Commit e45d25f

Browse files
committed
'Updated Docs'
2 parents 63e0c2e + ac905c1 commit e45d25f

File tree

2 files changed

+126
-1
lines changed

2 files changed

+126
-1
lines changed

pygorithm/data_structures/heap.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Author: ALLSTON MICKEY
2+
# Contributed: OMKAR PATHAK
3+
# Created On: 11th August 2017
4+
5+
from queue import Queue
6+
7+
# min-heap implementation as priority queue
8+
class Heap(Queue):
9+
def parent_idx(self, idx):
10+
return idx // 2
11+
12+
def left_child_idx(self, idx):
13+
return (idx * 2) + 1
14+
15+
def right_child_idx(self, idx):
16+
return (idx * 2) + 2
17+
18+
def insert(self, data):
19+
super().enqueue(data)
20+
if self.rear >= 1: # heap may need to be fixed
21+
self.heapify_up()
22+
23+
def heapify_up(self):
24+
'''
25+
Start at the end of the tree (last enqueued item).
26+
27+
Compare the rear item to its parent, swap if
28+
the parent is larger than the child (min-heap property).
29+
Repeat until the min-heap property is met.
30+
31+
Best Case: O(1), item is inserted at correct position, no swaps needed
32+
Worst Case: O(logn), item needs to be swapped throughout all levels of tree
33+
'''
34+
child = self.rear
35+
parent = self.parent_idx(child)
36+
while self.queue[child] < self.queue[self.parent_idx(child)]:
37+
# Swap (sift up) and update child:parent relation
38+
self.queue[child], self.queue[parent] = self.queue[parent], self.queue[child]
39+
child = parent
40+
parent = self.parent_idx(child)
41+
42+
def pop(self):
43+
''' Removes the lowest value element (highest priority, at root) from the heap '''
44+
min = super().dequeue()
45+
if self.rear >= 1: # heap may need to be fixed
46+
self.heapify_down()
47+
return min
48+
49+
def favorite(self, parent):
50+
''' Determines which child has the highest priority by 3 cases '''
51+
left = self.left_child_idx(parent)
52+
right = self.right_child_idx(parent)
53+
54+
if left <= self.rear and right <= self.rear: # case 1: both nodes exist
55+
if self.queue[left] <= self.queue[right]:
56+
return left
57+
else:
58+
return right
59+
elif left <= self.rear: # case 2: only left exists
60+
return left
61+
else: # case 3: no children (if left doesn't exist, neither can the right)
62+
return None
63+
64+
def heapify_down(self):
65+
'''
66+
Select the root and sift down until min-heap property is met.
67+
68+
While a favorite child exists, and that child is smaller
69+
than the parent, swap them (sift down).
70+
71+
Best Case: O(1), item is inserted at correct position, no swaps needed
72+
Worst Case: O(logn), item needs to be swapped throughout all levels of tree
73+
'''
74+
cur = ROOT = 0 # start at the root
75+
fav = self.favorite(cur) # determine favorite child
76+
while self.queue[fav] is not None:
77+
if self.queue[cur] > self.queue[fav]:
78+
# Swap (sift down) and update parent:favorite relation
79+
fav = self.favorite(cur)
80+
self.queue[cur], self.queue[fav] = self.queue[fav], self.queue[cur]
81+
cur = fav
82+
else:
83+
return
84+
85+
def time_complexities(self):
86+
return '''[Insert & Pop] Best Case: O(1), Worst Case: O(logn)'''
87+
88+
def get_code(self):
89+
''' returns the code for the current class '''
90+
import inspect
91+
return inspect.getsource(Heap)

tests/test_data_structure.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
# -*- coding: utf-8 -*-
12
import unittest
23

34
from pygorithm.data_structures import (
45
stack,
56
queue,
67
linked_list,
78
tree,
8-
graph)
9+
graph,
10+
heap)
911

1012
class TestStack(unittest.TestCase):
1113
def test_stack(self):
@@ -168,5 +170,37 @@ def test_cycle_in_undirected_graph(self):
168170

169171
self.assertTrue(myGraph.check_cycle())
170172

173+
class TestHeap(unittest.TestCase):
174+
def test_heap(self):
175+
myHeap = heap.Heap()
176+
myHeap.insert(6)
177+
myHeap.insert(3)
178+
myHeap.insert(5)
179+
myHeap.insert(12)
180+
myHeap.insert(1)
181+
182+
expectedResult = [1, 3, 5, 12, 6]
183+
self.assertEqual(myHeap.queue, expectedResult)
184+
185+
self.assertEqual(myHeap.pop(), 1)
186+
expectedResult = [3, 5, 12, 6]
187+
self.assertEqual(myHeap.queue, expectedResult)
188+
189+
self.assertEqual(myHeap.pop(), 3)
190+
expectedResult = [5, 12, 6]
191+
self.assertEqual(myHeap.queue, expectedResult)
192+
193+
self.assertEqual(myHeap.pop(), 5)
194+
expectedResult = [6, 12]
195+
self.assertEqual(myHeap.queue, expectedResult)
196+
197+
self.assertEqual(myHeap.pop(), 6)
198+
expectedResult = [12]
199+
self.assertEqual(myHeap.queue, expectedResult)
200+
201+
self.assertEqual(myHeap.pop(), 12)
202+
expectedResult = []
203+
self.assertEqual(myHeap.queue, expectedResult)
204+
171205
if __name__ == '__main__':
172206
unittest.main()

0 commit comments

Comments
 (0)