1. Introduction & Motivation
A plain binary heap gives you $O(\log n)$ insert, $O(\log n)$ extract-min, and $O(1)$ peek. But ask it to do one more thing — combine two entire heaps into one — and it has no good answer. The array-backed binary heap has exactly one way to merge: take every element of the smaller heap and insert it, one at a time, into the larger one. Merging a heap of size $m$ into a heap of size $n$ this way costs $O(m \log(n+m))$; when the two heaps are comparable in size, that is $O(n \log n)$ for a single merge — effectively as expensive as sorting all the elements from scratch.
That single missing operation motivates an entire family of data structures called mergeable heaps (also called meldable heaps): priority queues engineered so that combining two heaps is fast — from $O(\log n)$ down to $O(1)$ — often at the cost of giving up the tight, complete-binary-tree shape that makes an array-backed heap so simple. This lesson covers five such structures, roughly in order of increasing structural cleverness:
- Leftist Heap: tracks a "null-path length" per node to guarantee a short right spine, so merge only ever recurses down that spine.
- Skew Heap: the same merge idea as Leftist, but drops the bookkeeping entirely and just always swaps children — trading a worst-case guarantee for an amortized one.
- Pairing Heap: a multi-way tree where merge is a single comparison and a pointer attach — the simplest of the five to implement, and fast in practice.
- Binomial Heap: a forest of trees shaped like the binary representation of the heap's size, where merging two heaps is literally binary addition with carries.
- Fibonacci Heap: relaxes the Binomial Heap's strict shape to get $O(1)$ amortized insert, merge, and (critically) decrease-key — the structure that gives Dijkstra's algorithm its best known asymptotic running time.
All five support the same core contract as a binary heap — insert, find-min, extract-min — plus an efficient merge (sometimes called meld or union). Several of them also support decrease-key, which matters far beyond textbook exercises: it is the operation Dijkstra's algorithm leans on every time it finds a shorter path to a vertex already in the queue.
2. Prerequisites
This lesson assumes you are already comfortable with the standard array-backed binary heap: the heap-order property, heapify-up and heapify-down, $O(n)$ build-heap, and $O(\log n)$ insert/extract-min. Those fundamentals are covered in depth in Part 11: Heaps, Sorting & Hashing (see its "Heap Fundamentals" and "Heap Operations" sections) — this lesson does not re-derive them. What's new here is entirely about structure: none of the five heaps below use a flat array: they are all explicit node-and-pointer trees (or forests of trees), which is exactly what unlocks fast merging.
3. Leftist Heap
Merging two leftist heaps a and b: compare the two roots, keep the smaller as the new root, and recursively merge its right child with the other whole tree. After that recursive merge returns, compare the s-values of the new root's two children and swap them if the left child's s-value is smaller — restoring the invariant. insert is just merge(heap, singleton), and extract-min removes the root and merges its two children.
4. Skew Heap
Why does unconditional swapping still bound the amortized cost? Intuitively, every merge step walks one node further down the right spine of each input tree, then immediately turns that step into a left-spine step by swapping. A node can only be visited by a merge along a right spine a bounded number of times before the swapping forces it onto a much shorter path for future operations; a potential-function argument (assigning "credit" to nodes on the right spine of any subtree) shows the total work across any sequence of $n$ merges is $O(n \log n)$, even though a single pathological merge can briefly touch $O(n)$ nodes.
5. Pairing Heap
extract-min: removing the root leaves behind a list of orphaned child subtrees that must be recombined, using the "two-pass pairing" procedure below.
To extract the minimum: detach the root's list of children, then (1) pair them up left-to-right and merge each pair, and (2) combine the resulting merged trees right-to-left into one final tree. This specific two-pass order (rather than, say, merging strictly left-to-right) is what gives Pairing Heaps their good amortized behavior in practice.
6. Binomial Heap
Link: given two order-$k$ trees, compare their roots; the one with the larger value becomes the new leftmost child of the one with the smaller value, producing a single order-$(k{+}1)$ tree in $O(1)$. Merge (union): splice the two root lists together sorted by ascending order (like the merge step of merge sort), then walk the combined list left to right, "carrying" whenever two adjacent trees share the same order — identical in spirit to adding two binary numbers digit by digit. Extract-min: scan the root list for the minimum-valued root, remove it, reverse its list of children into a fresh small binomial heap, and merge that back into what remains.
7. Fibonacci Heap
Insert and merge become just root-list concatenation — no linking, no carrying, done lazily and left for later. All of that deferred cleanup work is paid for during extract-min, which "consolidates" the root list back down to one tree per degree. This laziness is what gives $O(1)$ amortized insert, merge, and (critically) decrease-key — the operation that makes Dijkstra's algorithm asymptotically faster.
Decrease-key needs one more mechanism to stay cheap: marking. When a node loses a child (because that child was cut away by a decrease-key elsewhere), it is marked. If an already-marked node loses a second child, it is itself cut from its parent and moved to the root list — and the cut cascades upward to its own parent (a "cascading cut"). This bounds how lopsided any tree can become: no node can lose more than one child "for free" before it, too, gets promoted to the root list.
The consolidate step below is written as a clearly-commented, straightforward pass rather than a micro-optimized one: it uses a hash map keyed by degree instead of a pre-sized array, and recomputes degree as "current number of children" instead of caching a separate field. Both choices trade a constant factor for clarity without changing the algorithm's correctness or its $O(\log n)$ amortized extract-min bound.
8. Complexity Comparison Table
"Amortized" bounds below hold over any sequence of operations from an empty heap; where a structure gives the same bound worst case and amortized, only one value is shown.
| Heap | Insert | Merge | Extract-Min | Decrease-Key |
|---|---|---|---|---|
| Leftist | $O(\log n)$ worst case | $O(\log n)$ worst case | $O(\log n)$ worst case | Not supported (no parent pointers) |
| Skew | $O(\log n)$ amortized | $O(\log n)$ amortized | $O(\log n)$ amortized | Not supported (no parent pointers) |
| Pairing | $O(1)$ worst case | $O(1)$ worst case | $O(\log n)$ amortized | $O(\log n)$ amortized (conjectured optimal) |
| Binomial | $O(\log n)$ worst case, $O(1)$ amortized | $O(\log n)$ worst case | $O(\log n)$ worst case | $O(\log n)$ worst case (needs parent pointers; not implemented above) |
| Fibonacci | $O(1)$ amortized | $O(1)$ amortized | $O(\log n)$ amortized | $O(1)$ amortized |
9. Applications & Alternatives
Choosing among mergeable heaps
- Leftist / Skew Heap: the simplest mergeable heaps to reach for in competitive programming when you need to merge priority queues (e.g. small-to-large merging on a tree) and don't need decrease-key.
- Pairing Heap: the practical favorite — simplest to implement well, excellent constant factors, and used as the priority queue backing several graph-algorithm libraries in practice, despite its amortized bounds being harder to pin down tightly in theory than Fibonacci's.
- Binomial Heap: a clean, fully worst-case-bounded mergeable heap; a natural fit when a system needs predictable per-operation latency rather than just a good amortized average, and its forest-of-trees shape maps directly onto binary counters and other "carry" structures.
- Fibonacci Heap: the textbook answer whenever decrease-key dominates the workload — Dijkstra's algorithm and Prim's minimum spanning tree algorithm are the canonical examples. In practice its large constant factors mean a $d$-ary heap or a Pairing Heap often wins on real hardware despite the worse asymptotic bound.
None of these are the only way to get a mergeable priority queue. A balanced BST (Part 10) already supports merge, insert, and extract-min in $O(\log n)$, at the cost of more memory overhead per node than a specialized heap. Concatenable structures like 2-3 finger trees generalize the idea further, supporting split and concatenate alongside priority operations. The right choice, as always, depends on which operation dominates the workload — merge-heavy, decrease-key-heavy, or extract-min-heavy — not on which structure is most famous.
10. Exercises & Mastery
Easy
- Given a working
merge(a, b)for a Skew Heap, implementinsert(root, value)as a single call tomergewith a freshly created singleton node.
Medium
- Given two Pairing Heaps, merge them and then extract the minimum from the combined heap. State which of the two original roots survives the merge and what happens to its sibling's subtree during the following extract-min.
Hard
- You are given a working array/binary-heap-backed implementation of Dijkstra's algorithm. Explain, step by step, how swapping its priority queue for a Fibonacci-Heap-backed one changes the algorithm's asymptotic running time, which specific priority-queue calls benefit, and why. Code is optional here — the goal is the design reasoning, not a rewritten implementation.
Review rhythm: tomorrow, redraw the Leftist Heap's leftist invariant and the Fibonacci Heap's marking rule from memory; next week, re-derive why Skew Heap's amortized bound holds despite no per-operation guarantee; several weeks later, trace a Binomial Heap merge as binary addition with carries on paper. Finally, explain to someone else why a plain binary heap cannot merge efficiently, and which of these five structures you'd reach for and why.
11. Summary Cheat Sheet
- A plain binary heap merges in $O(n \log n)$ by repeated insertion; "mergeable" (meldable) heaps exist specifically to make merge faster.
- Leftist Heap: tracks null-path length (s-value) to keep the right spine short; merge is $O(\log n)$ worst case.
- Skew Heap: same merge shape as Leftist, but unconditionally swaps children instead of tracking an invariant; $O(\log n)$ amortized, not worst case.
- Pairing Heap: a multi-way tree; merge is a single comparison and attach, $O(1)$; extract-min uses two-pass pairing to recombine children.
- Binomial Heap: a forest with at most one tree per order; merging is binary addition with carries.
- Fibonacci Heap: lazy root-list concatenation for insert/merge, with cleanup deferred to extract-min; marking and cascading cuts bound tree imbalance and give $O(1)$ amortized decrease-key.
- Fibonacci Heaps are the classic reason Dijkstra's algorithm reaches $O(E + V\log V)$ instead of $O((V+E)\log V)$.
- In practice, Pairing Heaps are frequently preferred over Fibonacci Heaps for their much smaller constant factors.