-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbinaryheap.py
131 lines (108 loc) · 3.5 KB
/
binaryheap.py
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
121
122
123
124
125
126
127
128
129
130
131
class BinaryHeap:
def __init__(self):
self.root = Node()
def peek(self):
"""Returns the root node as a tuple
() -> (str, int)
"""
return (self.root.key, self.root.val)
def insert(self, data):
"""Wrapper method for insert to start
at the root
Params: data - (key, val) to insert
() -> ()
"""
self.__insert(self.root, data)
def delete_max(self):
"""Wrapper method for delete_max to start
at the root
() -> ()
"""
self.__delete_max(self.root)
def __delete_max(self, node):
"""Delete the given node in-place
Params: node - node to delete
Node -> ()
"""
data = (None, None)
self.__set(node, data)
data_left = (node.left.key, node.left.val)
data_right = (node.right.key, node.right.val)
if node.left.val and node.right.val:
if node.left.val > node.right.val:
self.__insert(node, data_left)
self.__delete_max(node.left)
else:
self.__insert(node, data_right)
self.__delete_max(node.right)
elif node.left.val or node.right.val:
if node.left.val:
self.__insert(node, data_left)
self.__delete_max(node.left)
elif node.right.val:
self.__insert(node, data_right)
self.__delete_max(node.right)
else:
node.left = None
node.right = None
def __insert(self, current_node, data):
"""Inserts node at balanced position
Params: data - (key, val) tuple
(str, int) -> ()
"""
if not current_node.key or data[1] > current_node.val:
self.__replace(current_node, data)
else:
if current_node.dir:
self.__insert(current_node.left, data)
current_node.dir = False
else:
self.__insert(current_node.right, data)
current_node.dir = True
def __replace(self, node, data):
"""Replaces node with data and inserts
node1's data into the tree
Params: node - node to replace
data - (key, val) to replace with
* node should have a smaller val than data[1]
Node, (str, int) -> ()
"""
data1 = (node.key, node.val)
self.__set(node, data)
if data1[0] and data1[1]:
self.__insert(node, data1)
def __set(self, node, data):
"""Sets node to key, val
Node, str, int -> ()
"""
node.key = data[0]
node.val = data[1]
if not node.left:
node.left = Node()
if not node.right:
node.right = Node()
def __str__(self):
"""Wrapper for to_str
() -> () -> str
"""
return self.to_str(self.root)
def to_str(self, node, depth=0):
ret = ""
# Print right branch
if node.right:
ret += self.to_str(node.right, depth + 1)
# Print own value
ret += "\n" + (" "*depth) + str(node)
# Print left branch
if node.left:
ret += self.to_str(node.left, depth + 1)
return ret
class Node:
def __init__(self, key=None, val=None):
self.key = key
self.val = val
self.left = None
self.right = None
self.dir = False
def __str__(self):
return "({}, {})".format(self.key, self.val)