""" classical priority queue it supports an arbitrary comparison function and is good for arbitrary length queues. Based on pq2.py, optimized (about 3-4x faster). """ from bisect import insort class PQ0: """priority queue using insertion sorting (bisect) This seems to be the fastest way, unless you want to use a different comparison metric, or unless the set grows *very* large. """ def __init__(self, comparison = cmp): if comparison!=cmp: raise ValueError, "only cmp comparison supported for PQ0" self.data = [] def empty(self): return len(self.data)==0 def addelt(self, priority, elt): item = (priority, elt) insort(self.data, item) def largestp(self): return self.data[-1] def poplargest(self): data = self.data item = data[-1] del data[-1] return item def popsmallest(self): data = self.data item = data[0] del data[0] return item class PQueue: """basic priority queue, using classical heap structure""" def __init__(self, comparison = cmp): self.cmp = comparison self.data = [None] * 8 # presize for 8 elements # first element is always empty, first used is 1, no data yet self.free = 1 def empty(self): """empty test""" return self.free == 1 def addelt(self, priority, elt): """add element by decreasing priority""" index = self.free try: self.data[ index ] = (priority, elt) except IndexError: # self.data is too small, double its size length = len( self.data ) newdata = [ None ] * (2 * length) # store the old values newdata[:length] = self.data self.data = newdata # now there ought to be room! self.data[ index ] = (priority, elt) self.free = index + 1 return self._checkposition(index) def popsmallest(self): """get/pop element with smallest priority""" if self.free < 2: raise IndexError, "priority queue is empty" smallest = self.data[1] self._removeentry(1) return smallest def _removeentry(self, index): """internal: remove an entry""" # restructure the "tree" if other elements remain free = self.free data = self.data last = free - 1 if last > index: data[index] = data[last] data[last] = None self.free = last self._checkposition(index) else: data[index] = None self.free = last def smallestp(self): """get (priority, element) for smallest priority""" return self.data[1] # make sure a position has contents larger than parents, # and smaller than children, and if not, do a swap # and check the new position recursively... # def _checkposition(self, index): data = self.data comparison = self.cmp thisitem = data[index] thispriority = thisitem[0] free = self.free if index>=2: # check parent, possibly bubble up parent = index/2 parentitem = data[parent] parentpriority = parentitem[0] if comparison(parentpriority, thispriority)>0: while 1: data[parent] = thisitem data[index] = parentitem index = parent if index<2: return index parent = index/2 parentitem = data[parent] parentpriority = parentitem[0] if comparison(parentpriority, thispriority)<=0: return index # otherwise, check children # find the highest priority child: while 1: thechild = index*2 if thechild>=free: return index childitem = data[thechild] childpriority = childitem[0] otherchild = thechild+1 if otherchild