avl.go — the skeleton
Create avl.go. The usual skeleton; the bodies are yours.
Most of this file is lesson 11's code carried across unchanged — Get,
Keys, Range, Min, Max are identical with *node replaced by *avlNode.
Rotations change the shape, not the meaning. Copy them and do not feel like you
are cheating: that is the observation that an AVL tree is a BST.
Genuinely new: five functions — height, balance, fix, the two rotations, and
rebalance.
Worth noting:
heightmust be nil-safe. An absent subtree has height 0. Half of all AVL bugs are a missing nil check right here, and they show up as "sometimes unbalanced" rather than as a crash.fixruns on two nodes after a rotation, and the order matters. The one that moved down first, then the one that moved up — the second one's height depends on the first.- An equal key does not rebalance.
Puton an existing key only replaces the record; the shape did not change, so there is nothing to repair. - Rotations are not comparisons.
c.Hit()fires only when two keys are compared. Count rotations there too and step 6 stops working — and step 6 is precisely about what the counter cannot see. Height()isO(1)here — it returnsroot.h. In lesson 11 it had to walk the whole tree. That is a free dividend from the field you just added.
Insertion has to be recursive. Lesson 11's loop over &(*cur).left will not
do: the repair happens on the way back up, and a loop has no way back up.
rebalance returns the new subtree root, and the caller has to take that
value:
n.left = insert(n.left) // correct — the subtree may have a new root
insert(n.left) // wrong — a rotation happened and was thrown away
The second version compiles and reports no error. Len() climbs on every call,
because the counter is incremented where the leaf is created — but the leaf
itself is thrown away, so Get cannot find the key. Measured: the very first
test fails with Get("00000"): ok=false.
A silent no-op that still increments the count is a nastier failure than a
crash, and it is the reason the first thing avl_test.go checks is that every
key stored can be found again.