CS205 Data Structures
Use arrow keys or buttons to navigate
A collection where each element has a priority. The element with the highest priority (lowest key) is served first.
Patients are NOT seen in arrival order. The most critical case (lowest priority number) is treated first.
A priority queue is an ADT that supports inserting elements with keys and removing the element whose key is minimal (or maximal). Not FIFO!
A PQ stores entries — each is a (key, value) pair.
| Method | Description |
|---|---|
insert(k, v) | Insert entry with key k, value v |
removeMin() | Remove & return min-key entry |
min() | Return (don't remove) min-key entry |
size() | Number of entries |
isEmpty() | Is PQ empty? |
removeMin() and min() throw an error if called on an empty PQ. Always check isEmpty() first.
Keys define priority. But how do we compare them?
A valid comparison rule must satisfy:
A comparator is like a judge at a competition — swap in a different judge to rank contestants by a different criterion.
Any two keys must be comparable — this makes it a total order. The comparator pattern lets you swap ordering strategies without changing the PQ.
Insert fast, but finding the minimum requires scanning everything.
| Operation | Time |
|---|---|
insert | O(1) |
removeMin | O(n) |
min | O(n) |
size, isEmpty | O(1) |
Insert is O(1) — just append to the end. But removeMin is O(n) because we must scan every entry to find the smallest key.
Good for insert-heavy workloads with rare removes. Terrible if you remove frequently.
Keep entries sorted by key. Min is always at the front, but insertion requires walking.
| Operation | Time |
|---|---|
insert | O(n) |
removeMin | O(1) |
min | O(1) |
size, isEmpty | O(1) |
removeMin is O(1) — the smallest is always at front. But insert is O(n) — we walk the list to find the correct sorted position.
Good for remove-heavy workloads with rare inserts. Terrible if you insert frequently.
Neither list approach gives us the best of both worlds.
| Operation | Unsorted | Sorted |
|---|---|---|
insert(k,v) | O(1) | O(n) |
removeMin() | O(n) | O(1) |
min() | O(n) | O(1) |
Unsorted list = throwing clothes into a pile. Fast to add, slow to find what you need.
Sorted list = keeping a perfectly organized closet. Slow to put away, fast to grab the right item.
What if both insert and removeMin were O(log n)?
Use an unsorted list PQ to sort — this is Selection Sort!
Phase 1: n × O(1) = O(n)
Phase 2: n + (n-1) + ... + 1 = n(n+1)/2 = O(n²)
Total: O(n²)
Each removeMin selects the minimum from the remaining unsorted elements — exactly what Selection Sort does!
Use a sorted list PQ to sort — this is Insertion Sort!
Phase 1: 1 + 2 + ... + n = n(n+1)/2 = O(n²)
Phase 2: n × O(1) = O(n)
Total: O(n²)
Like sorting playing cards: pick up each card and slide it into the right spot among cards you're already holding.
Both PQ-based sorts are O(n²). Is there a middle ground?
The binary heap achieves O(log n) for both insert and removeMin by using a complete binary tree with the heap-order property.
The heap is like a corporate hierarchy: the CEO (min key) is always at the top. Promoting someone (insert) bubbles them up through levels. Firing the CEO (removeMin) promotes from below.
Full heap details → next lecture!
PQs store entries, not bare keys. Each entry is a (key, value) pair.
The key = boarding group number. The value = you (the passenger). The airline decides your priority, not your name.
Entries decouple "what you store" from "how it's prioritized." This makes the PQ reusable across many domains.
Sometimes you need to change a key or remove an arbitrary entry — not just the minimum.
| Method | Description |
|---|---|
remove(e) | Remove entry e |
replaceKey(e, k) | Change key of e to k |
replaceValue(e, v) | Change value of e |
An adaptable PQ lets you modify entries already in the queue. Essential for graph algorithms like Dijkstra's and Prim's.
Operating systems use priority queues to decide which process runs next.
insert(priority, process)removeMin() to pick the next processLike a hospital with one doctor: the most critical patient always gets treated next, but new patients arrive at any time and get triaged into the queue.
The PQ ensures that system-critical tasks (interrupts, real-time processes) always preempt lower-priority work like background backups.
Simulate a system by processing events in chronological order.
Events are entries with time as the key. Processing an event often creates new future events. The PQ always gives us the chronologically next event — no need to iterate through all possibilities.
Like a director with a schedule of scenes to film. Each scene might add new scenes. The PQ picks the one that happens earliest in the story timeline.
The priority queue is the engine behind the famous shortest-path algorithm.
Dijkstra "greedily" picks the unvisited vertex with the smallest known distance using removeMin(). With a heap-based PQ, the algorithm runs in O((V + E) log V).
Without a PQ, finding the next closest vertex costs O(V) per step → O(V²) total. With a heap PQ, each step is O(log V) — a huge speedup on large graphs.
Full details in the Graph Algorithms unit.
What does removeMin() return after this sequence?
What entry does the third removeMin() return?
Build optimal prefix-free codes for data compression using a priority queue.
The PQ always merges the two least frequent nodes. This greedy strategy produces an optimal prefix code. Two removeMin + one insert per step.
Rare characters get long codes (deep in tree), frequent characters get short codes (near root). Total bit usage is minimized.
This PQ-based sort has a bug — find and fix it
Wait — this code looks correct. But what if we change the PQ to a max-heap (removeMax instead of removeMin)?
What's wrong and how do you fix it?
How do all PQ implementations stack up?
Choose your implementation:
Unsorted List — few removes, many inserts, small n
Sorted List — few inserts, many removes, small n
Binary Heap — general purpose PQ — best default
Balanced BST — need ordered iteration or range queries too
The binary heap is the sweet spot: O(log n) insert and removeMin, O(1) min, simple array-based storage, and it gives us Heap Sort at O(n log n).
A balanced BST (AVL, Red-Black) also achieves O(log n) for everything, but has higher constant factors and more complex implementation. Heaps are preferred when you only need PQ operations.
Match each scenario to the best PQ implementation
Everything on one slide
| Unsorted | Sorted | Heap | |
|---|---|---|---|
insert | O(1) | O(n) | O(log n) |
removeMin | O(n) | O(1) | O(log n) |
min | O(n) | O(1) | O(1) |
Next up: Binary Heaps — the data structure that makes PQs efficient.
Test your understanding — 3 questions
Q1: Which PQ implementation gives O(n²) Selection Sort?
Q2: Why does an adaptable PQ need location-aware entries?
Q3: What makes a binary heap better than both list-based PQ implementations?
Identify which PQ-sort each animation represents
What prints at the end?
What are the two lines of output?