The target and the guiding principle
- Targets: constant-time insertion and constant-time decrease-key, with delete-min at
O(log n)44:17,44:52. - Guiding principle, shared by many amortized data structures: be lazy — do not do work until you are forced to
44:17,44:52.
Laziness step 1 — defer all consolidation to delete-min
- A binomial heap eagerly restores the "one tree per rank" invariant on every insert, for no good reason: if you only ever insert, that merging work is pure waste
45:12,45:41. - Fibonacci heap insert: just append the new node to the top-level linked list
45:41. - All consolidation happens during delete-min, which has to walk the root list anyway
46:02.
Laziness step 2 — the "really lazy" decrease-key
- The bubble-up decrease-key walks the tree height,
O(log n); an adversary can repeat decrease-keys in a high-rank tree forever46:52. - Ultra-lazy alternative (a student's suggestion): decrease the key; if the heap order property is now violated, cut the edge to the parent and splice the subtree into the top-level list
47:17,47:34,48:22. - Design heuristic offered: start with the laziest thing possible, then add back only the bare minimum needed to make the bounds work
47:51.
Why pure laziness fails
The binomial-heap argument that "max rank ≤ log n" rested on rank-k trees having 2^k nodes 50:11, 50:30. Unrestricted cutting destroys that:
- Take a rank-
ktree and decrease-key every grandchild, cutting each away. - You are left with a tree of rank
kholding onlyk+1items51:00,51:19. - Rank no longer certifies size, so the
O(log n)bound on delete-min collapses51:19. - Intuition given: the root "thinks his tree is big, but little does he know he's losing all of his descendants" — the loss must somehow be communicated upward
52:02.
The one extra rule: cascading cuts and mark bits
If a node
ploses one child to a cut, that is fine. Ifploses a second child, cutpout too and make its subtree a top-level tree.52:27
- The rule recurses:
pmay itself be the second lost child of its own parent, which then cuts itself out, and so on — these are the cascading cuts53:33,1:09:44. - Clarification for a student: no key swapping is involved. If
ploses childxand then childy, theny's subtree becomes one top-level tree andpwith its remainder becomes a separate top-level tree —pandyno longer share a tree53:57,54:12,54:29. - Implementation: one mark bit per node —
mark(x) = 1iffxhas lost a child. The bit is reset when the node is itself cut out59:50,1:00:31.
flowchart TD
A["decrease-key(x, k)"] --> B{"heap order<br/>violated?"}
B -- no --> C["done: O(1)"]
B -- yes --> D["cut x, move its subtree<br/>to the root list, clear mark(x)"]
D --> E{"parent p<br/>already marked?"}
E -- no --> F["set mark(p) = 1; done"]
E -- yes --> G["cut p out too<br/>(cascading cut)"]
G --> E