Skip to content

Commit c2dbf17

Browse files
committed
Add PriorityQueue
1 parent ff00ddd commit c2dbf17

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

heaps.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,101 @@ def replace(self, item):
2828

2929
def peek(self):
3030
return self._items[0]
31+
32+
33+
class PriorityQueue:
34+
"""Priority queue implemented using a heap.
35+
36+
This implementation ensures stability: items with the same priority
37+
are returned in the order they were added, and the values of the
38+
items themselves are never compared.
39+
40+
>>> q = PriorityQueue()
41+
>>> q.push('lmao')
42+
>>> q.push('ayy', priority=1)
43+
>>> while q:
44+
... print(q.pop())
45+
ayy
46+
lmao
47+
48+
The queue may be destructively iterated over:
49+
50+
>>> q.push('ayy')
51+
>>> q.push('lmao')
52+
>>> len(q), list(q)
53+
(2, ['ayy', 'lmao'])
54+
>>> len(q), list(q)
55+
(0, [])
56+
57+
"""
58+
59+
def __init__(self, items=None):
60+
from itertools import count
61+
self._heap = []
62+
self._counter = count()
63+
64+
def push(self, item, priority=0):
65+
from heapq import heappush
66+
# Entries are stored as tuples, which heapq compares when they
67+
# are pushed or popped. The priority and a unique ID are stored
68+
# as the first two elements to make sure the item itself is
69+
# never included in any comparison.
70+
#
71+
# The heapq module implements a min-heap, so invert the priority
72+
# and make the IDs monotonically increase to ensure stability.
73+
heappush(self._heap, (-priority, next(self._counter), item))
74+
75+
def pop(self):
76+
from heapq import heappop
77+
_, _, item = heappop(self._heap)
78+
return item
79+
80+
def peek(self):
81+
"""
82+
>>> q = PriorityQueue()
83+
>>> q.peek()
84+
Traceback (most recent call last):
85+
...
86+
IndexError: list index out of range
87+
>>> q.push(None)
88+
>>> q.peek()
89+
"""
90+
_, _, item = self._heap[0]
91+
return item
92+
93+
def __bool__(self):
94+
"""
95+
>>> q = PriorityQueue()
96+
>>> bool(q)
97+
False
98+
>>> q.push(None)
99+
>>> bool(q)
100+
True
101+
>>> q.pop()
102+
>>> bool(q)
103+
False
104+
"""
105+
return bool(self._heap)
106+
107+
def __len__(self):
108+
"""
109+
>>> q = PriorityQueue()
110+
>>> len(q)
111+
0
112+
>>> q.push(None)
113+
>>> len(q)
114+
1
115+
>>> q.pop()
116+
>>> len(q)
117+
0
118+
"""
119+
return len(self._heap)
120+
121+
def __next__(self):
122+
try:
123+
return self.pop()
124+
except IndexError:
125+
raise StopIteration
126+
127+
def __iter__(self):
128+
return self

0 commit comments

Comments
 (0)