Skip to content

Commit 59d7089

Browse files
committed
Create min_heap.py
1 parent 43f4b22 commit 59d7089

File tree

1 file changed

+175
-0
lines changed

1 file changed

+175
-0
lines changed

min_heap.py

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import unittest
2+
3+
4+
class MinHeap(object):
5+
6+
def __init__(self):
7+
self.storage = []
8+
9+
10+
def swap(self, a, b):
11+
self.storage[a], self.storage[b] = self.storage[b], self.storage[a]
12+
13+
14+
def size(self):
15+
return len(self.storage)
16+
17+
18+
def peak(self):
19+
return self.storage[0]
20+
21+
22+
def insert(self, value):
23+
self.storage.append(value)
24+
index = self.size() - 1
25+
self.bubbleUp(index)
26+
27+
28+
def get_parent(self, child):
29+
if child % 2 == 0:
30+
return (child - 2)/2
31+
else:
32+
return (child - 1)/2
33+
34+
35+
def bubbleUp(self, child):
36+
parent = self.get_parent(child)
37+
38+
while (child > 0) and parent >= 0 and (self.storage[child] < self.storage[parent]):
39+
self.swap(child, parent)
40+
child = parent
41+
parent = self.get_parent(child)
42+
43+
44+
def remove_peak(self):
45+
self.swap(0, self.size()-1)
46+
min_elem = self.storage.pop()
47+
self.bubbleDown(0)
48+
49+
return min_elem
50+
51+
52+
def get_child(self, parent):
53+
child1 = 2 * parent + 1
54+
child2 = 2 * parent + 2
55+
56+
if child1 >= self.size():
57+
return
58+
elif child2 >= self.size():
59+
return child1
60+
elif self.storage[child1] < self.storage[child2]:
61+
return child1
62+
else:
63+
return child2
64+
65+
66+
def bubbleDown(self, parent):
67+
child = self.get_child(parent)
68+
69+
while child is not None and self.storage[parent] > self.storage[child]:
70+
self.swap(child, parent)
71+
parent = child
72+
child = self.get_child(parent)
73+
74+
75+
def remove(self, item):
76+
last_index = self.size() - 1
77+
swap_index = 0
78+
79+
# can implement with hash table instead of for loop to keep this in
80+
# O(logn) time complexity, however need to keep track of every element
81+
# in hash table and update hash table in each method +O(n) space
82+
for i in range(len(self.storage)):
83+
if item == self.storage[i]:
84+
swap_index = i
85+
self.storage[i], self.storage[last_index] = self.storage[last_index], self.storage[i]
86+
87+
self.bubbleUp(swap_index)
88+
self.bubbleDown(swap_index)
89+
90+
removed_item = self.storage.pop()
91+
92+
return removed_item
93+
94+
95+
96+
def __repr__(self):
97+
return '<storage = {}>'.format(self.storage)
98+
99+
100+
101+
class Testing(unittest.TestCase):
102+
103+
def setUp(self):
104+
self.test = MinHeap()
105+
self.test.storage = [4, 5, 6, 7, 8]
106+
107+
def test_swap(self):
108+
self.test.swap(0, 3)
109+
self.assertEqual(repr(self.test), '<storage = [7, 5, 6, 4, 8]>', 'swap is incorrect')
110+
111+
def test_size(self):
112+
self.assertEqual(self.test.size(), 5, 'size is incorrect')
113+
114+
def test_peak(self):
115+
self.assertEqual(self.test.peak(), 4, 'peak is the wrong value')
116+
117+
def test_insert(self):
118+
self.test.storage = []
119+
self.test.insert(7)
120+
self.test.insert(4)
121+
self.test.insert(10)
122+
self.test.insert(1)
123+
self.test.insert(8)
124+
self.test.insert(11)
125+
self.test.insert(9)
126+
self.test.insert(2)
127+
print self.test
128+
self.assertEqual(repr(self.test), '<storage = [1, 2, 9, 4, 8, 11, 10, 7]>', 'did not insert new value properly')
129+
130+
def test_get_parent(self):
131+
self.assertEqual(self.test.get_parent(7), 3, 'getting child\'s parent index is incorrect')
132+
133+
134+
def test_bubbleUp(self):
135+
self.test.insert(1)
136+
self.assertEqual(repr(self.test), '<storage = [1, 5, 4, 7, 8, 6]>', 'did not bubble up correctly')
137+
self.test.insert(10)
138+
self.assertEqual(repr(self.test), '<storage = [1, 5, 4, 7, 8, 6, 10]>', 'did not bubble up correctly')
139+
self.test.insert(2)
140+
self.assertEqual(repr(self.test), '<storage = [1, 2, 4, 5, 8, 6, 10, 7]>', 'did not bubble up correctly')
141+
self.test.insert(9)
142+
self.assertEqual(repr(self.test), '<storage = [1, 2, 4, 5, 8, 6, 10, 7, 9]>', 'did not bubble up correctly')
143+
144+
145+
def test_remove_peak(self):
146+
self.test.storage = [1, 2, 4, 11]
147+
self.assertEqual(self.test.remove_peak(), 1, 'did not remove correct value')
148+
self.assertEqual(self.test.remove_peak(), 2, 'did not remove correct value')
149+
self.assertEqual(self.test.remove_peak(), 4, 'did not remove correct value')
150+
self.assertEqual(self.test.remove_peak(), 11, 'did not remove correct value')
151+
152+
153+
def test_get_child(self):
154+
self.assertEqual(self.test.get_child(0), 1, 'did not select the right child index')
155+
156+
157+
def test_bubbleDown(self):
158+
self.test.storage = [1, 2, 4, 11]
159+
self.test.remove_peak()
160+
self.assertEqual(repr(self.test), '<storage = [2, 11, 4]>', 'did not bubble down correctly')
161+
self.test.remove_peak()
162+
self.assertEqual(repr(self.test), '<storage = [4, 11]>', 'did not bubble down correctly')
163+
self.test.remove_peak()
164+
self.assertEqual(repr(self.test), '<storage = [11]>', 'did not bubble down correctly')
165+
self.test.remove_peak()
166+
self.assertEqual(repr(self.test), '<storage = []>', 'did not bubble down correctly')
167+
168+
169+
def test_remove(self):
170+
self.assertEqual(self.test.remove(8), 8, 'did not remove correct value')
171+
self.assertEqual(repr(self.test), '<storage = [4, 5, 6, 7]>', 'did not bubble down correctly')
172+
173+
174+
if __name__ == '__main__':
175+
unittest.main()

0 commit comments

Comments
 (0)