PCCST303 · Module 3: Trees and Graphs

Priority Queue

An ordinary queue removes elements in the order they arrived, first in, first out. A priority queue removes elements according to a different rule entirely: whichever element has the highest (or lowest) priority goes first, regardless of when it arrived.

Priority Queue

Definition

A priority queue stores elements each with an associated priority. The element removed next is always the one with the highest (or, for a min-priority queue, the lowest) priority, not necessarily the one that arrived first.

A hospital emergency room is the standard example: patients are not treated in arrival order, but by urgency.

Normal patient     priority 1
Urgent patient      priority 4
Critical patient    priority 5

A critical patient who just walked in is treated before a normal patient who has been waiting for an hour, since priority overrides arrival order.

Operations

OperationMeaning
InsertAdd a new element with its priority
PeekLook at the highest (or lowest) priority element without removing it
DeleteRemove the highest (or lowest) priority element

Why a binary heap implements it

Key Idea

A binary heap is an efficient implementation of a priority queue: a max heap gives a max-priority queue, a min heap gives a min-priority queue. The heap's own root-holds-the-extreme property is exactly the "always know the highest/lowest" property a priority queue needs.

This mirrors a distinction already seen with stacks: a stack is an abstract behavior (LIFO), and an array or a linked list is one way to implement that behavior. Similarly:

Priority queue → the behavior (remove by priority)
Binary heap    → the data structure that implements it efficiently

Just as a stack could be implemented other ways (a plain array with O(n) push, for instance), a priority queue could too. The heap is the standard choice because its O(log n) insert and delete beat the worse bounds of a plain sorted or unsorted list.

A max-priority queue holding four patient priorities (P1=2, P2=5, P3=4, P4=1), stored as a max heap:

P3:4P1:2P2:5
Index
P2:5
P3:4
P1:2
012

The highest priority, 5, sits at the root, index 0, exactly where peek looks, so no search across the other elements is needed.

Insert and delete, using the heap operations directly

Because a priority queue is a heap underneath, its insert and delete are literally the heap insertion (bubble-up) and heap root deletion (heapify-down) algorithms, just described in priority-queue terms:

PQ_INSERT(A, N, ITEM, PRIORITY)
// A is the array of (element, priority) pairs
// N is the current number of elements in the priority queue
// ITEM is the new element, PRIORITY is its priority
 
1. A[N] = (ITEM, PRIORITY)
2. i = N
3. N = N + 1
 
4. While i > 0:
       parent = (i - 1) / 2      (integer division)
 
       If A[parent].priority >= A[i].priority:
           Break
 
       Swap A[parent] and A[i]
       i = parent
 
5. Return
PQ_DELETE_MAX(A, N)
// A is the array of (element, priority) pairs
// N is the current number of elements in the priority queue
 
1. If N == 0:
       PRINT "UNDERFLOW"
       Return
2. MAX = A[0]
3. A[0] = A[N-1]
4. N = N - 1
5. HEAPIFY_DOWN(A, N, 0)   // same heapify-down used to delete a heap's root
6. Return MAX

Example: inserting P4 with priority 1 into the heap above. (PQ_INSERT, Steps 1-3) It is placed at the next open slot, index 3:

Index
P2:5
P3:4
P1:2
P4:1
0123
P4:1P3:4P1:2P2:5

(Step 4) i = 3 > 0, so the loop runs: parent = (3-1)/2 = 1, whose priority is 4. Since A[parent].priority = 4 >= A[i].priority = 1, the If condition holds and the loop breaks: no swap is needed, and P4 stays a leaf.

Example: PQ_DELETE_MAX. (Step 1) N = 4 != 0, so there is no underflow. (Step 2) Save the root, MAX = A[0], which is P2 with priority 5. (Step 3) Move the last element, A[N-1], which is P4 with priority 1, to the root. (Step 4) Shrink the heap: N = 3:

Index
P4:1
P3:4
P1:2
012
P3:4P1:2P4:1

(Step 5) Call HEAPIFY_DOWN(A, 3, 0): compare P4 (priority 1) with its two children, P3 (priority 4) and P1 (priority 2), and swap with the larger, P3:

Index
P3:4
P4:1
P1:2
012
P4:1P1:2P3:4

P4 (now at index 1) has no children within the current heap size, so the process stops. (Step 6) P2 with priority 5 has been returned, and the heap correctly holds P3 with priority 4 as the new maximum.

Time complexity summary

OperationTime
Peek at the highest/lowest priority elementO(1)
Insert one elementO(log n)
Delete the highest/lowest priority elementO(log n)
Build a priority queue from an unordered array of n elementsO(n)
Peek is O(1) because the extreme element always sits at the root, index 0 in the array representation, so no search is needed. Insert and delete cost O(log n) because they involve bubble-up or heapify-down, bounded by the heap's height.

Quick recall

  • Priority queue: removes elements by priority, not arrival order (unlike a plain FIFO queue).
  • Operations: insert, peek (highest/lowest), delete (highest/lowest).
  • A binary heap is the standard implementation: max heap → max-priority queue, min heap → min-priority queue.
  • Peek is O(1) (the extreme is always at the root); insert and delete are O(log n).
  • "Priority queue" names the behavior; "heap" names the structure that implements it efficiently, the same way "stack" and "array/linked-list" are separate layers.