"A priority queue is a queue that ignores arrival order and serves by importance instead. The heap is how you build one — and in Python, it's already built: the heapq module."
The Priority Queue ADT
A priority queue is an abstract data type with two operations: insert an item with a priority, and remove the highest-priority item. Unlike a plain FIFO queue (oldest first), a priority queue always hands you the most important element next — exactly the emergency-room triage from the very first track. The heap is its canonical implementation: O(log n) insert, O(log n) remove-best, O(1) peek-best. When someone says 'priority queue,' they almost always mean 'heap.'
Python's heapq: Already Done For You
You rarely implement the sift-up/sift-down yourself — Python's heapq module gives you a battle-tested heap over an ordinary list: heappush, heappop, heapify, plus combos like heappushpop and helpers nlargest/nsmallest. Two things to burn in: it's a min-heap (smallest pops first), and it operates on a plain list in place. That's the whole API for 90% of real uses.
The Two Idioms You'll Always Need
- Max-heap via negation. heapq is min-only. Want the largest out first? Push
-valueand negate again on the way out. (For 'top-k largest',heapq.nlargest(k, data)does it directly.) - Priority + payload via tuples. Push
(priority, item)and the heap orders by priority. But beware: tuples compare element-by-element, so if two priorities tie, Python tries to compare the items — which crashes if they're not comparable (or orders them in a way you didn't intend). The fix is a monotonic counter as a tiebreaker: push(priority, count, item), wherecountis unique and breaks every tie before the item is ever compared.
Where Priority Queues Run the World
OS task schedulers (run the highest-priority ready process), event-driven simulations (process the next-soonest event), bandwidth/QoS shaping, the A* and Dijkstra shortest-path algorithms (next track pops the closest frontier node), Huffman coding, and 'top-k' analytics all sit on a priority queue. It's the structure for 'a stream of things arrives, and I must always handle the most important one next' — one of the most common shapes in real systems.
Pippa's Confession
TypeError: '<' not supported between instances of 'Task'. I'd pushed (priority, task) tuples, two tasks tied on priority, and Python tried to compare the Task objects to break the tie. Dad's one-line fix — insert a unique counter, (priority, next(counter), task) — guaranteed the tie was always broken before the task was ever touched. It's the kind of gotcha you only learn by hitting it; now it's the first thing I reach for with heapq.