Commit df7c4cde authored by Raymond Hettinger's avatar Raymond Hettinger

Clean-up and improve the priority queue example in the heapq docs.

parent a5bc34fa
...@@ -173,36 +173,36 @@ changes to its priority or removing it entirely. Finding a task can be done ...@@ -173,36 +173,36 @@ changes to its priority or removing it entirely. Finding a task can be done
with a dictionary pointing to an entry in the queue. with a dictionary pointing to an entry in the queue.
Removing the entry or changing its priority is more difficult because it would Removing the entry or changing its priority is more difficult because it would
break the heap structure invariants. So, a possible solution is to mark an break the heap structure invariants. So, a possible solution is to mark the
entry as invalid and optionally add a new entry with the revised priority:: entry as removed and add a new entry with the revised priority::
pq = [] # the priority queue list pq = [] # list of entries arranged in a heap
counter = itertools.count(1) # unique sequence count entry_finder = {} # mapping of tasks to entries
task_finder = {} # mapping of tasks to entries REMOVED = '<removed-task>' # placeholder for a removed task
INVALID = 0 # mark an entry as deleted counter = itertools.count() # unique sequence count
def add_task(priority, task, count=None): def add_task(task, priority=0):
if count is None: 'Add a new task or update the priority of an existing task'
if task in entry_finder:
remove_task(task)
count = next(counter) count = next(counter)
entry = [priority, count, task] entry = [priority, count, task]
task_finder[task] = entry entry_finder[task] = entry
heappush(pq, entry) heappush(pq, entry)
def get_top_priority(): def remove_task(task):
while True: 'Mark an existing task as REMOVED. Raise KeyError if not found.'
entry = entry_finder.pop(task)
entry[-1] = REMOVED
def pop_task():
'Remove and return the lowest priority task. Raise KeyError if empty.'
while pq:
priority, count, task = heappop(pq) priority, count, task = heappop(pq)
if count is not INVALID: if task is not REMOVED:
del task_finder[task] del entry_finder[task]
return task return task
raise KeyError('pop from an empty priority queue')
def delete_task(task):
entry = task_finder[task]
entry[1] = INVALID
def reprioritize(priority, task):
entry = task_finder[task]
add_task(priority, task, entry[1])
entry[1] = INVALID
Theory Theory
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment