queue.py 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. # min heap used in the FMT*
  2. import collections
  3. import heapq
  4. import itertools
  5. class MinheapPQ:
  6. """
  7. A priority queue based on min heap, which takes O(logn) on element removal
  8. https://docs.python.org/3/library/heapq.html#priority-queue-implementation-notes
  9. """
  10. def __init__(self):
  11. self.pq = [] # lis of the entries arranged in a heap
  12. self.nodes = set()
  13. self.entry_finder = {} # mapping of the item entries
  14. self.counter = itertools.count() # unique sequence count
  15. self.REMOVED = '<removed-item>'
  16. def put(self, item, priority):
  17. '''add a new task or update the priority of an existing item'''
  18. if item in self.entry_finder:
  19. self.check_remove(item)
  20. count = next(self.counter)
  21. entry = [priority, count, item]
  22. self.entry_finder[item] = entry
  23. heapq.heappush(self.pq, entry)
  24. self.nodes.add(item)
  25. def check_remove(self, item):
  26. if item not in self.entry_finder:
  27. return
  28. entry = self.entry_finder.pop(item)
  29. entry[-1] = self.REMOVED
  30. self.nodes.remove(item)
  31. def get(self):
  32. """Remove and return the lowest priority task. Raise KeyError if empty."""
  33. while self.pq:
  34. priority, count, item = heapq.heappop(self.pq)
  35. if item is not self.REMOVED:
  36. del self.entry_finder[item]
  37. self.nodes.remove(item)
  38. return item
  39. raise KeyError('pop from an empty priority queue')
  40. def top_key(self):
  41. return self.pq[0][0]
  42. def enumerate(self):
  43. return self.pq
  44. def allnodes(self):
  45. return self.nodes