Source code for tryalgo.our_heap
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""\
A min heap
christoph dürr et jill-jênn vie - 2015-2019
"""
# snip{
[docs]
class OurHeap:
""" min heap
* heap: is the actual heap, heap[1] = index of the smallest element
* rank: inverse of heap with rank[x]=i iff heap[i]=x
* n: size of the heap
:complexity: init O(n log n), len O(1),
other operations O(log n) in expectation
and O(n) in worst case, due to the usage of a dictionary
"""
def __init__(self, items):
self.heap = [None] # index 0 will be ignored
self.rank = {}
for x in items:
self.push(x)
def __len__(self):
return len(self.heap) - 1
[docs]
def push(self, x):
"""Insert new element x in the heap.
Assumption: x is not already in the heap"""
assert x not in self.rank
i = len(self.heap)
self.heap.append(x) # add a new leaf
self.rank[x] = i
self.up(i) # maintain heap order
[docs]
def pop(self):
"""Remove and return smallest element"""
root = self.heap[1]
del self.rank[root]
x = self.heap.pop() # remove last leaf
if self: # if heap is not empty
self.heap[1] = x # move the last leaf
self.rank[x] = 1 # to the root
self.down(1) # maintain heap order
return root
# snip}
# snip{ our_heap_up_down
[docs]
def up(self, i):
"""The value of heap[i] has decreased. Maintain heap invariant."""
x = self.heap[i]
while i > 1 and x < self.heap[i // 2]:
self.heap[i] = self.heap[i // 2]
self.rank[self.heap[i // 2]] = i
i //= 2
self.heap[i] = x # insertion index found
self.rank[x] = i
[docs]
def down(self, i):
"""the value of heap[i] has increased. Maintain heap invariant."""
x = self.heap[i]
n = len(self.heap)
while True:
left = 2 * i # climb down the tree
right = left + 1
if (right < n and self.heap[right] < x and
self.heap[right] < self.heap[left]):
self.heap[i] = self.heap[right]
self.rank[self.heap[right]] = i # move right child up
i = right
elif left < n and self.heap[left] < x:
self.heap[i] = self.heap[left]
self.rank[self.heap[left]] = i # move left child up
i = left
else:
self.heap[i] = x # insertion index found
self.rank[x] = i
return
[docs]
def update(self, old, new):
"""Replace an element in the heap
"""
i = self.rank[old] # change value at index i
del self.rank[old]
self.heap[i] = new
self.rank[new] = i
if old < new: # maintain heap order
self.down(i)
else:
self.up(i)
# snip}