-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathheap.py
154 lines (118 loc) · 3.51 KB
/
heap.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
class Heap_Item:
"""
Heap item data structure.
"""
def __init__(self, k, v):
"""
Generates a heap item with key k and value v.
"""
self.key = k
self.value = v
def __repr__(self):
"""
Represents a heap item.
"""
return "({},{})".format(self.key, self.value)
class Min_Heap:
"""
Min-Heap data structure.
"""
def __init__(self):
"""
Generates an empty min-heap.
"""
self.heap = []
self.index = {}
def key(self, v):
"""
Returns the key of the heap element with value v.
"""
return self.heap[self.index[v]].key
def left(self, i):
"""
Returns the i-th item's left child index.
"""
return 2*i+1
def right(self, i):
"""
Returns the i-th item's right child index.
"""
return 2*(i+1)
def parent(self, i):
"""
Returns the i-th item's parent index.
"""
return (i-1)//2
def min_heapify(self, i):
"""
Restores the min-heap property on the i-th item, assuming
that its left and right sub-heaps are correct min-heaps.
"""
l = self.left(i)
r = self.right(i)
min = i
if l < len(self) and self.heap[l].key < self.heap[min].key:
min = l
if r < len(self) and self.heap[r].key < self.heap[min].key:
min = r
if min != i:
self.swap(i, min)
self.min_heapify(min)
def extract_min(self):
"""
Extracts the pair (key, value) containing the smallest key
from the heap.
"""
if not self:
return None
self.swap(0, len(self)-1)
min = self.heap.pop()
del self.index[min.value]
self.min_heapify(0)
return (min.key, min.value)
def insert(self, k, v):
"""
Inserts the pair (k, v) into the heap.
"""
self.heap.append(Heap_Item(k,v))
self.index[v] = len(self)-1
self.decrease_key(v,k)
def decrease_key(self, v, k):
"""
Decreases the key of the heap element containing value
v to k.
"""
# NOTE: assumes that value v is present in the heap
# NOTE: assumes that the key of the element holding
# value v is >= k.
i = self.index[v]
item = self.heap[i]
item.key = k
p = self.parent(i)
while i > 0 and k < self.heap[p].key:
self.heap[i] = self.heap[p]
self.index[self.heap[p].value] = i
i, p = p, self.parent(p)
self.heap[i] = item
self.index[item.value] = i
def swap(self, i, j):
"""
Swaps the i-th and j-th items in the heap.
"""
self.index[self.heap[i].value], self.index[self.heap[j].value] = j, i
self.heap[i], self.heap[j] = self.heap[j], self.heap[i]
def __len__(self):
"""
Returns the number of items in the heap.
"""
return len(self.heap)
def __bool__(self):
"""
Returns True if the heap is not empty, and False otherwise.
"""
return len(self.heap) > 0
def __contains__(self, v):
"""
Checks whether value v is present in the heap.
"""
return v in self.index