-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmaxheap.py
More file actions
120 lines (98 loc) · 3.99 KB
/
maxheap.py
File metadata and controls
120 lines (98 loc) · 3.99 KB
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
# MAX HEAP Implementation
# A max-heap is a complete binary tree in which the value in each internal node
# is greater than or equal to the values in the children of that. Its very FAST.
# Main condition: Parent >= Children (Each node is <= of its parent)
# Main structure: COMPLETE BINARY TREE (2-tree)
# condition: Every node except the leaves has two children,
# every level its completed except for possible leaf elements.
# Nodes that are leaves does not have right siblings.
# All nodes are added towards left (first fill the left side)
# Methods:
# Peek: get the max value (root)
# Push: add value to the end, float up to the right position
# Pop: removes the max, return the max, swap the max with the last node then remove.
# Bubble down the swapped value (root) to the right position, compare first left side
# and needs to check all the tree for accomplish the main condition.
# Implements using list, for this approach we need to omit the firsts position (0 index)
# to apply the following formulas to traverse trough the heap
# max value = heap[1]
# parent = index//2
# left child = index * 2
# right child = (index * 2) + 1
class MaxHeap:
def __init__(self, items=None) -> None:
if items is None:
items = []
self._heap = [0]
for item in items:
self._heap.append(item)
self._floatUp(len(self._heap) - 1)
def __str__(self) -> str:
if len(self._heap) > 1:
return f"MAX HEAP: max{self._heap[1]} items{self._heap[1:]}"
else:
return f"MAX HEAP: empty"
def push(self, item):
self._heap.append(item)
self._floatUp(len(self._heap) - 1)
def peek(self):
if len(self._heap) > 1:
return self._heap[1]
else:
return None
def _get_parent(self, position: int) -> int:
return position // 2
def _get_left_child(self, position: int) -> int:
return position * 2
def _get_right_child(self, position: int) -> int:
return (position * 2) + 1
def _swapp(self, child_position: int, parent_position: int) -> None:
temp = self._heap[parent_position]
self._heap[parent_position] = self._heap[child_position]
self._heap[child_position] = temp
# self._heap[parent_position], self._heap[child_position] = self._heap[child_position], self._heap[parent_position]
def pop(self):
if len(self._heap) > 2:
last_index = len(self._heap) - 1
# Swapp the max and the last
self._swapp(last_index, 1)
# Remove from heap
item = self._heap.pop()
# Reorder heap
self._bubbleDown(1)
return item
elif len(self._heap) == 2:
return self._heap.pop()
else:
return None
def _floatUp(self, position) -> None:
parent_index = self._get_parent(position)
if position == 1 or parent_index == 0:
return
if self._heap[parent_index] >= self._heap[position]:
return
self._swapp(position, parent_index)
self._floatUp(parent_index)
def _bubbleDown(self, position: int) -> None:
left_child_index = self._get_left_child(position)
if left_child_index <= len(self._heap) - 1:
if self._heap[position] < self._heap[left_child_index]:
self._swapp(left_child_index, position)
self._bubbleDown(left_child_index)
else:
return
right_child_index = self._get_right_child(position)
if right_child_index <= len(self._heap) - 1:
if self._heap[position] < self._heap[right_child_index]:
self._swapp(right_child_index, position)
self._bubbleDown(right_child_index)
else:
return
# TEST
mh = MaxHeap([95, 3, 21])
print(mh)
mh.push(10)
print(mh)
print(f"PEEK: {mh.peek()}")
print(f"POP: {mh.pop()}")
print(mh)