A priority queue is an abstract data type where each element has a priority, and removal always returns the highest-priority element (or lowest, depending on convention). Unlike a regular FIFO Queue, the order in which elements come out is determined by their priority, not their insertion time.

Operations

The standard interface:

  • insert(item, priority) — add an item with a given priority.
  • extractMax() (or extractMin()) — remove and return the highest-priority item. Errors or returns NULL if empty.
  • peek() — return the highest-priority item without removing it.
  • isEmpty() — state query.

Some priority queues also support:

  • changePriority(item, newPriority) — update an existing item’s priority.
  • remove(item) — remove a specific item.

Use cases

The “extract the most important next” pattern matches many real-world problems:

  • Process scheduling. The OS scheduler picks the next process to run by priority. Real-time systems use priority queues to enforce deadlines.
  • Dijkstra’s algorithm. The next vertex to process is the one with the smallest tentative distance.
  • A pathfinding*. Pick the next position to expand by lowest estimated total cost.
  • Discrete event simulation. Events are processed in time order; the priority queue holds future events.
  • Network packet prioritization. Quality-of-service systems extract higher-priority packets first.
  • Top-K queries. Maintain a priority queue of size K to track the K largest/smallest items in a stream.
  • Huffman coding. Build the encoding tree by repeatedly extracting the two lowest-frequency nodes.

Implementations

The interface is abstract — the underlying data structure can vary:

ImplementationInsertExtract maxPeek
Unsorted array
Sorted array
Binary heap
Balanced BST
Fibonacci heap amortized amortized

The binary heap is the standard implementation — it gives for both critical operations and uses minimal extra memory. See Heap (data structure).

For applications where insertions vastly outnumber extractions (Dijkstra-style), a Fibonacci heap can theoretically improve total time, but the constant factor makes it rarely competitive in practice.

Min vs max priority queue

A max-priority queue extracts the element with the highest priority (largest key). A min-priority queue extracts the smallest. Implementations are symmetric — a max-heap gives a max-PQ; flip the comparison and you have a min-PQ.

In many algorithm presentations:

  • “Priority queue” without qualifier often means max-PQ.
  • Dijkstra/A*/event simulation typically use min-PQ.
  • Top-K-largest typically uses min-PQ of size K (so the smallest in the top-K is at the top, ready to be evicted by anything bigger).

Stability

A priority queue is stable if elements with equal priority come out in insertion order (FIFO). Most heap-based PQs are not stable by default — equal-priority elements can shuffle during heap operations.

To enforce stability, augment each item with a tiebreaker (insertion timestamp, sequence number) and use a priority pair (priority, timestamp).

The Canadian Triage and Acuity Scale is a real-world stability concern: medical priority levels 1–5 (Resuscitation, Emergent, Urgent, Less Urgent, Non-Urgent), where patients within the same level should be served first-come-first-served. A naive max-heap on priority alone can violate this.

Why heaps and not BSTs

Both heaps and balanced BSTs give for the priority queue operations. Why is the heap the standard choice?

  • Memory efficiency: heaps store as a flat array, no pointers. BSTs need 2-3 pointers per node.
  • Cache locality: array layout dominates linked-tree layout for traversal-heavy workloads.
  • Simpler implementation: a heap is just an array with a few index-arithmetic helpers.

BSTs win when you need additional operations beyond priority queue basics — finding arbitrary elements by key, range queries, in-order traversal. Plain priority queues don’t need those.

For the standard implementation, see Heap (data structure). For the queue’s FIFO cousin without priorities, see Queue.