DSA DSA In Depth
0%
lesson fibonacci-heapbinomial-heapleftist-heap

Mergeable Priority Queues: Leftist, Skew, Binomial & Fibonacci Heaps (O(1) Decrease-Key)

7 min read Module 3.1: Binary Trees, Traversals, BSTs & Priority Heaps Updated Oct 23, 2026
📄 Cheat Sheet
Fibonacci Heaps — How to Invent an Extremely Clever Data Structure
SithDev Fibonacci Heaps — How to Invent an Extremely Clever Data Structure Watch on YouTube ↗

Complete derivation of Binomial Trees, lazy root-list consolidation, cascading cuts, potential function Φ = t(H) + 2m(H), and Golden Ratio degree bound.

0:00 / --:--

From Leftist/Skew Spine Merging to Binomial & Fibonacci Forests

Let us compare the four classical mergeable priority queue families:

  1. Leftist Heap (Crane 1972) & Skew Heap (Sleator & Tarjan 1986): A Leftist Heap stores the null-path length $\text{npl}(u)$ (shortest distance to a null child) at each node and enforces $\text{npl}(u.\text{left}) \ge \text{npl}(u.\text{right})$. Consequently, the right spine has length at most $\lfloor \log_2(N + 1) \rfloor$. Merging two Leftist Heaps recursively merges their right spines in $O(\log N)$ worst-case time and swaps children where needed. A Skew Heap drops the stored $\text{npl}$ field entirely and unconditionally swaps left and right children at every node along the merged right spine, achieving $O(\log N)$ amortized time!
  2. Binomial Heap (Vuillemin 1978): A Binomial Tree $B_k$ of order $k$ has $2^k$ nodes and is formed by linking two $B_{k-1}$ trees (attaching one as the leftmost child of the other's root). Any integer $N = \sum b_k 2^k$ decomposes uniquely into at most $\lfloor \log_2 N \rfloor + 1$ Binomial Trees, so meld(H₁, H₂) is literally ripple-carry binary addition on tree orders in $O(\log N)$ time.
  3. Fibonacci Heap (Fredman & Tarjan 1987): Relaxes the Binomial Heap by allowing multiple trees of the same degree in a circular doubly-linked root list during insert and meld ($O(1)$ actual time), only consolidating trees of equal degree by array-indexed bucket linking during extractMin.
  4. Pairing Heap (Fredman, Sedgewick, Sleator & Tarjan 1986): A self-adjusting multi-ary tree where extractMin links root children in adjacent pairs left-to-right and then coalesces right-to-left. Achieves $O(1)$ insert/meld, $O(\log N)$ extractMin, and $o(\log N)$ ($Omega(\log \log N)$) amortized decreaseKey with a fraction of the pointer overhead of Fibonacci Heaps.
Operation Binary / $d$-Ary Heap Leftist / Skew / Binomial Heap Fibonacci Heap (Amortized) Pairing Heap (Amortized)
findMin() O(1) O(1) O(1) O(1)
insert(x) O(log N) (O(1) avg) O(log N) (O(1) amort. Binomial) O(1) O(1)
meld(H₁, H₂) Θ(N) O(log N) O(1) O(1)
decreaseKey(u, k) O(log_d N) O(log N) O(1) Amortized o(log N)
extractMin() O(d log_d N) O(log N) O(log N) Amortized O(log N) Amortized

Fibonacci Heap Potential Proof: $\Phi(H) = t(H) + 2m(H)$ & Golden Ratio Degree Bound

Define the potential function $\Phi(H) = t(H) + 2m(H)$, where $t(H)$ is the number of trees in the root list and $m(H)$ is the number of marked internal nodes (nodes that have already lost 1 child since becoming a child of their current parent).

  • Why the factor of $2$ in $2m(H)$? When decreaseKey(u, k) violates heap order ($k < p.\text{key}$), we cut $u$ from its parent $p$ and move $u$ to the root list. If $p$ was already marked, we recursively cut $p$ as well (a cascading cut) and unmark $p$. Suppose a cascading cut performs $c$ cuts: the actual work is $O(c)$. How does $\Phi(H)$ change? Each of the $c$ cut nodes enters the root list ($\Delta t = +c$), the $c - 1$ cascading ancestors become unmarked while at most 1 highest ancestor becomes newly marked ($\Delta m \le -(c - 1) + 1 = 2 - c$). Thus: $$\Delta \Phi \le c + 2(2 - c) = 4 - c \implies \text{Amortized Cost} = c + (4 - c) = O(1)!$$ One unit of released mark potential pays for the cut and root-list insertion; the second unit pays for marking the final ancestor at the top of the cascade!
  • Why is the name "Fibonacci"? Because a node is cut as soon as it loses a second child, the $i$-th child $y_i$ of any node $x$ of degree $k$ must have degree at least $i - 2$. Therefore, the minimum subtree size $s_k$ of a degree-$k$ node satisfies $s_k \ge 2 + \sum_{i=2}^k s_{i-2} = F_{k+2} \ge \phi^k$, where $\phi = \frac{1+\sqrt{5}}{2} \approx 1.618$. Hence maximum degree $D(N) \le \lfloor \log_\phi N \rfloor \approx 1.44 \log_2 N$!
Fibonacci Heap Consolidation / Cascading Cuts & Hierarchical Timer Wheel
O(1) Amortized decreaseKey · O(1) Timer Wheel

Compare Fredman-Tarjan Fibonacci Heaps (Φ = t(H) + 2m(H), degree-table consolidation, and cascading cuts) against Varghese-Lauck O(1) Hierarchical Timing Wheels used in Linux kernel hrtimers and Kafka.

Step 1 / 9
Custom Input:
Timeline

Invariant & State

Potential Function Φ(H) = t(H) + 2m(H): Lazy insert & meld simply splice into root list in O(1) actual time (ΔΦ = +1).
🌳 Live 2D Hierarchical Tree Topology — Fibonacci Heap Consolidation / Cascading Cuts & Hierarchical Timer Wheel Visited/Active Pivot/Root Resolved
root 3 [0] 7 [1] 10 [2] 18 [3] 12 [4] 24 [5]
Lazy Root List (t(H)=4 trees, m(H)=1 marked node y): Potential Φ = t + 2m = 6
Min Root [3] (deg 0)
Root [7] (deg 0)
Root [10]—child [18] (deg 1)
Root [12]—marked [24*] (deg 1)
Heap Operation
Before extractMin / decreaseKey
Amortized Cost
Φ = 4 + 2(1) = 6
Degree Invariant
Max Degree D(N) ≤ ⌊log_φ N⌋
[Step 1] Potential Function Φ(H) = t(H) + 2m(H): Lazy insert & meld simply splice into root list in O(1) actual time (ΔΦ = +1).

Visualizing Fibonacci Heap Cascading Cuts & Degree-Table Consolidation

Before decreaseKey(u: 24 → 5): Ancestors p, g are Marked (★) r:3 g:7★ p:9★ u:5 After Cascading Cut (c = 3 cuts to Root List): r:3 u:5 p:9 g:7 Δt = +3 (u, p, g added to root list) Δm = -2 (p and g unmarked; r is root so never marked) ΔΦ = Δt + 2Δm = 3 + 2(-2) = -1 ⇒ Amortized Cost = O(1)! Subtree Size Bound: size(deg k) ≥ F_{k+2} ≥ φ^k ⇒ D(N) ≤ 1.44 log₂ N
flowchart TD DK["decreaseKey(u, newKey)"] --> Update["u.key = newKey p = u.parent"] Update --> Viol{"p != null AND u.key < p.key ?"} Viol -- "No" --> CheckMin["Update minRoot if u.key < minRoot.key"] Viol -- "Yes" --> Cut["cut(u, p): move u to Root List u.marked = false"] Cut --> Cascade["cascadingCut(p): while p.parent != null: if !p.marked: p.marked = true; break else: cut(p, p.parent); p = p.parent"] Cascade --> CheckMin

Hardware Reality: Why Fibonacci Heaps Lose to 4-Ary Heaps in Real-World Dijkstra

Despite its optimal $O(E + V \log V)$ asymptotic bound, a Fibonacci Heap node requires 4 pointers (parent, child, leftSibling, rightSibling) plus degree and marked fields—totaling 48 to 64 bytes of overhead per element and triggering 4–8 L3 cache misses per circular list splice. Moreover, on real road networks and sparse graphs, $E = O(V)$ and the vast majority of tentative distance relaxations do not even trigger decreaseKey. Consequently, a flat 4-ary heap (or radix heap) beats Fibonacci Heaps by $5\times$ to $15\times$ in wall-clock execution time on every graph fitting in RAM!

Implementation: Skew Heap $O(\log N)$ Amortized Meld in 12 Lines of C++

When you genuinely need a pointer-based mergeable priority queue in production or competitive programming, the Skew Heap provides $O(\log N)$ amortized meld, push, and pop in just a dozen lines of code with zero balance metadata fields:

// C++20: Skew Heap — Self-Adjusting Mergeable Priority Queue in O(log N) Amortized Time
#include <utility>

struct SkewNode {
    int key;
    SkewNode *left = nullptr, *right = nullptr;
    explicit SkewNode(int k) : key(k) {}
};

// Merges two Skew Heaps in O(log N) amortized time by unconditionally swapping children
SkewNode* meld(SkewNode* a, SkewNode* b) {
    if (!a) return b;
    if (!b) return a;
    if (b->key < a->key) std::swap(a, b);
    // Recursively merge b with a's right spine, then swap a's children
    a->right = meld(a->right, b);
    std::swap(a->left, a->right);
    return a;
}

SkewNode* push(SkewNode* root, int key) {
    return meld(root, new SkewNode(key));
}

SkewNode* popMin(SkewNode* root) {
    SkewNode* nextRoot = meld(root->left, root->right);
    delete root;
    return nextRoot;
}

Failure Modes & Adversarial Pitfalls

  • Single-Operation Worst-Case Latency Spikes in Fibonacci Heaps: All $O(1)$ and $O(\log N)$ guarantees on Fibonacci Heaps are amortized. If you insert $N$ elements in $O(1)$ time each, the root list contains $N$ trees; the very first extractMin() must consolidate all $N$ trees in $\Theta(N)$ worst-case time! Never use a Fibonacci or Skew Heap in hard real-time audio/kernel paths; use a Leftist Heap, Brodal Queue, or array 4-ary heap instead.
  • Forgetting to Clear u.marked = false Upon Cut: When a node $u$ is cut and moved to the root list, its marked bit MUST be reset to false, otherwise future consolidations inherit stale mark bits and break the potential invariant.
Check yourself Question 1 of 4
Concept Check Structural Properties of an Order-k Binomial Tree B_k recall

A Binomial Heap represents a priority queue as a forest of Binomial Trees. Which set of properties holds for a Binomial Tree B_k of order k?

⚡ Interactive Challenge · Staff Level

Algorithmic Design & Complexity Check

Analyze the invariant, asymptotic bound, and hardware behavior before selecting.

Asymptotically, Dijkstra's algorithm runs in O(E + V log V) with a Fibonacci Heap versus O((E + V) log_4 V) with an Indexed 4-Ary Heap. Why do production routing engines (e.g., OSRM, GraphHopper) strongly prefer 4-ary heaps over Fibonacci Heaps?

Key Takeaways

Leftist Heaps maintain npl(left) >= npl(right) so the right spine has length <= log₂(N+1), enabling worst-case O(log N) meld; Skew Heaps achieve O(log N) amortized meld by unconditionally swapping children along the merged spine.
Binomial Heaps decompose N into power-of-2 Binomial Trees B_k where B_k is formed by linking two B_{k-1} trees, supporting O(log N) meld via binary ripple-carry addition.
Fibonacci Heaps achieve O(1) amortized insert, meld, and decreaseKey using lazy root lists, cascading cuts, and potential Φ(H) = t(H) + 2m(H).
Because each node can lose at most 1 child before being cut, a Fibonacci Heap node of degree k has at least F_{k+2} >= φ^k descendants, bounding max degree to <= 1.44 log₂ N.
Was this lesson helpful? Spot an issue or have a suggestion? Let us know on GitHub.
Report an issue