Skip to content

Commit 4826836

Browse files
committed
Day 38: implement a heap pt 1
1 parent 03a3190 commit 4826836

File tree

2 files changed

+235
-0
lines changed

2 files changed

+235
-0
lines changed

day38/README.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
Today I'm going to implement a min heap.
2+
3+
What is a heap?
4+
5+
From http://www.cprogramming.com/tutorial/computersciencetheory/heap.html:
6+
7+
"A heap is a partially sorted binary tree. Although a heap is not completely
8+
in order, it conforms to a sorting principle: every node has a value less
9+
(for the sake of simplicity, we will assume that all orderings are from
10+
least to greatest) than either of its children. Additionally, a heap is
11+
a "complete tree" -- a complete tree is one in which there are no gaps
12+
between leaves. For instance, a tree with a root node that has only one
13+
child must have its child as the left node. More precisely, a complete tree
14+
is one that has every level filled in before adding a node to the next level,
15+
and one that has the nodes in a given level filled in from left to right,
16+
with no breaks."
17+
18+
Basically, a one-node min heap might look something like this:
19+
20+
```
21+
7
22+
```
23+
24+
And a two-node min heap might look something like this:
25+
26+
```
27+
7
28+
/
29+
9
30+
```
31+
32+
three nodes:
33+
34+
```
35+
7
36+
/ \
37+
9 8
38+
```
39+
40+
four nodes:
41+
42+
```
43+
7
44+
/ \
45+
10 18
46+
/
47+
19
48+
```
49+
50+
and so on.
51+
52+
Here are some specs for my basic min heap that contains `n` integers:
53+
54+
getMin - takes no arguments, extracts and returns the minimum value in the heap.
55+
The rest of the heap is reorganized so that the min value is still at
56+
the top. Finishes in `O(n)` time.
57+
58+
peek - takes no arguments, returns the minimum value in the heap. Should return
59+
in `O(1)` time.
60+
61+
push - takes an integer as an argument and adds it into the heap, returning
62+
nothing. Should complete in `O(logn)` time.
63+
64+
heapify - takes an array of integers and forms a heap out of them. Should run in
65+
`O(nlogn)` (?) time.
66+
67+
size - takes no arguments and returns the number of integers in the heap `n`
68+
in `O(1)` time.
69+
70+
isEmpty - takes no arguments and returns `True` if there are no elements in the
71+
heap, and `False` if there ARE elements in the heap in `O(1)` time.
72+
73+
## Code
74+
75+
[Python](./heap.py)
76+
77+
## Follow-up
78+
79+
Why use a heap?
80+
81+
If some kind of ordering is required, i.e. max or min ordering, a heap is an
82+
efficient way to maintain that ordering even when elements are being deleted
83+
and added. The tree structure of the heap allows you to find elements in
84+
`O(logn)` time rather than `O(n)` time like in a normal array or linked list.

day38/heap.py

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
class MinHeap:
2+
def __init__(self, arr=[]):
3+
if len(arr) > 0:
4+
self.heap = self.heapify(arr)
5+
else:
6+
self.heap = []
7+
8+
self.size = 0
9+
10+
def getMin(self):
11+
if self.size > 0
12+
ret = self.heap[0] #[1]
13+
self.heap[0] = self.heap[-1] #[1]
14+
self.heap.pop() #[]
15+
self.size -= 1
16+
self.bubbleDown() #[]
17+
return ret
18+
19+
def peek(self):
20+
if self.size > 0
21+
return self.heap[0]
22+
23+
def push(self, val):
24+
self.heap.append(val)
25+
self.bubbleUp()
26+
self.size += 1
27+
28+
def heapify(self, arr):
29+
heap = []
30+
self.size = len(arr)
31+
return heap
32+
33+
def size(self):
34+
return self.size
35+
36+
def isEmpty(self):
37+
return self.size == 0
38+
39+
def testPush():
40+
heap = MinHeap()
41+
heap.push(2)
42+
assert heap.root.val == 2
43+
44+
heap.push(3)
45+
assert heap.root.val == 2
46+
47+
heap.push(1)
48+
assert heap.root.val == 1
49+
50+
heap.push(5)
51+
assert heap.root.val == 1
52+
53+
heap.push(-1)
54+
assert heap.root.val == -1
55+
56+
def testHeapify():
57+
def isMinHeap(heap):
58+
if heap == None:
59+
return True
60+
61+
if heap.root.left:
62+
left = heap.root.val < heap.root.left.val
63+
else:
64+
left = True
65+
66+
if heap.root.right:
67+
right = heap.root.val < heap.root.right.val
68+
else:
69+
right = True
70+
71+
return isMinHeap(heap.root.left) and isMinHeap(heap.root.right) and left and right
72+
73+
heap1 = MinHeap([1, 2, 3, 4, 5])
74+
heap2 = MinHeap([])
75+
heap3 = MinHeap([5, 4, 3, 2, 1])
76+
heap4 = MinHeap([3, 1])
77+
heap5 = MinHeap([0, -1, 1, -2, 2])
78+
assert isMinHeap(heap1)
79+
assert isMinHeap(heap2)
80+
assert isMinHeap(heap3)
81+
assert isMinHeap(heap4)
82+
assert isMinHeap(heap5)
83+
84+
def testGetMin():
85+
heap = MinHeap([2, 5, 20])
86+
assert heap.getMin() == 2
87+
assert heap.getMin() == 5
88+
89+
heap1 = MinHeap([1, 2, 3, 4, 5])
90+
assert heap1.getMin() == 1
91+
assert heap1.getMin() == 2
92+
93+
heap2 = MinHeap([5, 4, 3, 2, 1])
94+
assert heap2.getMin() == 1
95+
assert heap2.getMin() == 2
96+
97+
heap3 = MinHeap([2, 5, 3, 7, -1])
98+
assert heap3.getMin() == -1
99+
assert heap3.getMin() == 2
100+
101+
def testPeek():
102+
heap = MinHeap([2, 5, 20])
103+
assert heap.peek() == 2
104+
assert heap.peek() == 2
105+
106+
heap1 = MinHeap([1, 2, 3, 4, 5])
107+
assert heap1.peek() == 1
108+
assert heap1.peek() == 1
109+
110+
heap2 = MinHeap([5, 4, 3, 2, 1])
111+
assert heap2.peek() == 1
112+
assert heap2.peek() == 1
113+
114+
heap3 = MinHeap([2, 5, 3, 7, -1])
115+
assert heap3.peek() == -1
116+
assert heap3.peek() == -1
117+
118+
def testSize():
119+
heap = MinHeap()
120+
assert heap.size() == 0
121+
122+
heap2 = MinHeap([1])
123+
assert heap.size() == 1
124+
125+
heap3 = MinHeap([1, 2, 3, 4])
126+
assert heap.size() == 4
127+
128+
def testIsEmpty():
129+
heap = MinHeap()
130+
assert heap.isEmpty()
131+
132+
heap2 = MinHeap([1])
133+
assert not heap.isEmpty()
134+
135+
heap3 = MinHeap([1, 2, 3])
136+
assert not heap.isEmpty()
137+
138+
def testEverything():
139+
assert True
140+
141+
def tests():
142+
testPush()
143+
testHeapify()
144+
testGetMin()
145+
testPeek()
146+
testSize()
147+
testIsEmpty()
148+
testEverything()
149+
150+
if __name__ == "__main__":
151+
tests()

0 commit comments

Comments
 (0)