Skip to content

Commit 908517a

Browse files
committed
Fix heap unit test
1 parent 6426213 commit 908517a

File tree

2 files changed

+116
-1
lines changed

2 files changed

+116
-1
lines changed

pygorithm/data_structures/heap.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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(Heap, self).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 (first 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+
child = self.rear
32+
parent = self.parent_idx(child)
33+
while self.queue[child] < self.queue[self.parent_idx(child)]:
34+
# Swap (sift up) and update child:parent relation
35+
self.queue[child], self.queue[parent] = self.queue[parent], self.queue[child]
36+
child = parent
37+
parent = self.parent_idx(child)
38+
39+
def pop(self):
40+
''' Removes the lowest value element (highest priority) from the heap '''
41+
min = self.dequeue()
42+
if self.rear >= 1: # heap may need to be fixed
43+
self.heapify_down()
44+
return min
45+
46+
def favorite(self, parent):
47+
''' Determines which child has the highest priority by 3 cases '''
48+
left = self.left_child_idx(parent)
49+
right = self.right_child_idx(parent)
50+
51+
if left <= self.rear and right <= self.rear: # case 1: both nodes exist
52+
if self.queue[left] <= self.queue[right]:
53+
return left
54+
else:
55+
return right
56+
elif left <= self.rear: # case 2: only left exists
57+
return left
58+
else: # case 3: no children (if left doesn't exist, neither can the right)
59+
return None
60+
61+
def heapify_down(self):
62+
'''
63+
Select the root and sift down until min-heap property is met.
64+
65+
While a favorite child exists, and that child is smaller
66+
than the parent, swap them (sift down).
67+
'''
68+
cur = ROOT = 0 # start at the root
69+
fav = self.favorite(cur) # determine favorite child
70+
while self.queue[fav] is not None:
71+
if self.queue[cur] > self.queue[fav]:
72+
# Swap (sift down) and update parent:favorite relation
73+
fav = self.favorite(cur)
74+
self.queue[cur], self.queue[fav] = self.queue[fav], self.queue[cur]
75+
cur = fav
76+
else:
77+
return
78+
79+
def get_code(self):
80+
''' returns the code for the current class '''
81+
import inspect
82+
return inspect.getsource(Heap)

tests/test_data_structure.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
queue,
66
linked_list,
77
tree,
8-
graph)
8+
graph,
9+
heap)
910

1011
class TestStack(unittest.TestCase):
1112
def test_stack(self):
@@ -168,5 +169,37 @@ def test_cycle_in_undirected_graph(self):
168169

169170
self.assertTrue(myGraph.check_cycle())
170171

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

0 commit comments

Comments
 (0)