Rotations Keep the Height

The rotations are the last operations that can leave a cached height out of date.

The only addition to rightRotation is two updateHeight calls:

private Node<K, V> rightRotation(Node<K, V> root) {
  Node<K, V> child = root.left;
  root.left = child.right;
  child.right = root;
  updateHeight(root);  // root is now below child
  updateHeight(child);
  return child;
}

After the pointer changes, root and child are the only nodes whose children changed, so they are the only two whose heights can be wrong. The subtrees A, B, and C from the rotation pictures kept their shape, so their heights are still correct, and two updates are enough.

This is the bottom-up rule: root is now below child, and child’s new height is computed from root’s, so updateHeight(root) comes first.

leftRotation is the mirror, with the same two lines in the same order:

private Node<K, V> leftRotation(Node<K, V> root) {
  Node<K, V> child = root.right;
  root.right = child.left;
  child.left = root;
  updateHeight(root);  // root is now below child
  updateHeight(child);
  return child;
}

The double rotations need no change at all. We wrote each one as two single rotations in a row. Each single rotation now updates the two heights it changes, so when a double rotation finishes, every node it moved already has a correct height.