1
# Priority dictionary using binary heaps
2
# David Eppstein, UC Irvine, 8 Mar 2002
4
# Implements a data structure that acts almost like a dictionary, with two modifications:
5
# (1) D.smallest() returns the value x minimizing D[x]. For this to work correctly,
6
# all values D[x] stored in the dictionary must be comparable.
7
# (2) iterating "for x in D" finds and removes the items from D in sorted order.
8
# Each item is not removed until the next item is requested, so D[x] will still
9
# return a useful value until the next iteration of the for-loop.
10
# Each operation takes logarithmic amortized time.
12
from __future__ import generators
14
class priorityDictionary(dict):
16
'''Initialize priorityDictionary by creating binary heap of pairs (value,key).
17
Note that changing or removing a dict entry will not remove the old pair from the heap
18
until it is found by smallest() or until the heap is rebuilt.'''
23
'''Find smallest item after removing deleted items from front of heap.'''
25
raise IndexError, "smallest of empty priorityDictionary"
27
while heap[0][1] not in self or self[heap[0][1]] != heap[0][0]:
31
smallChild = 2*insertionPoint+1
32
if smallChild+1 < len(heap) and heap[smallChild] > heap[smallChild+1] :
34
if smallChild >= len(heap) or lastItem <= heap[smallChild]:
35
heap[insertionPoint] = lastItem
37
heap[insertionPoint] = heap[smallChild]
38
insertionPoint = smallChild
42
'''Create destructive sorted iterator of priorityDictionary.'''
50
def __setitem__(self,key,val):
51
'''Change value stored in dictionary and add corresponding pair to heap.
52
Rebuilds the heap if the number of deleted items gets large, to avoid memory leakage.'''
53
dict.__setitem__(self,key,val)
55
if len(heap) > 2 * len(self):
56
self.__heap = [(v,k) for k,v in self.iteritems()]
57
self.__heap.sort() # builtin sort probably faster than O(n)-time heapify
60
insertionPoint = len(heap)
62
while insertionPoint > 0 and newPair < heap[(insertionPoint-1)//2]:
63
heap[insertionPoint] = heap[(insertionPoint-1)//2]
64
insertionPoint = (insertionPoint-1)//2
65
heap[insertionPoint] = newPair
67
def setdefault(self,key,val):
68
'''Reimplement setdefault to pass through our customized __setitem__.'''