Why naive rotate-to-root fails
- The obvious idea — "rotate
xrepeatedly until it is the root" — provably does not rebalance32:34. - Counterexample walked through in class: a fully unbalanced path
6 → 5 → 4 → 3 → 2 → 1. After repeatedly rotating6to the root, the tree becomes6on top with1below it and2,3,4,5strung out — the depth wasnbefore and is stillnafter33:16,33:42,34:04.
Definition
Let y = parent(x) and z = parent(y). Repeat until x is the root 35:02, 35:42, 38:29:
| Case | Condition | Action | Timestamp |
|---|---|---|---|
| 1 ("zig") | y is the root (x has no grandparent) | rotate(x) | 36:17, 37:53 |
| 2 ("zig-zig") | Same direction: x left of y and y left of z, or right/right | rotate(y) then rotate(x) | 36:17, 36:58, 37:53 |
| 3 ("zig-zag") | Opposite directions: x left of y and y right of z, or vice versa | rotate(x) then rotate(x) | 36:58, 38:29 |
- The only structural difference between case 2 and case 3 is which node is rotated first — case 2 rotates the parent first, case 3 rotates
xtwice. That single choice is what makes the analysis work37:53,38:29.
flowchart TD
S["splay(x)"] --> Q1{"is x the root?"}
Q1 -->|yes| DONE["done"]
Q1 -->|no| Q2{"is parent(x) the root?"}
Q2 -->|yes| C1["Case 1: rotate(x)"]
Q2 -->|no| Q3{"x and y in<br/>same direction?"}
Q3 -->|"left-left / right-right"| C2["Case 2: rotate(y); rotate(x)"]
Q3 -->|"left-right / right-left"| C3["Case 3: rotate(x); rotate(x)"]
C1 --> Q1
C2 --> Q1
C3 --> Q1
Shapes produced
- Case 2 transforms
z → y → x(with subtreesA, Bunderx, thenC,D) intox → y → zwithA, B, C, Dredistributed left-to-right39:03,39:35. - Case 3 lifts
xabove bothyandz, makingyandzits two children40:32,40:52,41:33.
Sanity check: splaying the leaf of a path
- Applying
splayto the deepest node of a long path (the same worst case that defeats naive rotation) halves the depth: roughly half the path ends up on the new spine, each with one node hanging off it41:33,42:37,45:13. - Explicitly not a proof, only evidence the definition is heading in the right direction
45:13.