Proofs: Order-statistic tree
These are the human proofs of Order-statistic tree, at full length.
Select and rank are correct, and updates keep the sizes right full
This proof shows: correctness.
Write for the number of nodes in the subtree of , with , and for the sorted list of the keys of the subtree of , indexed from 0. The size invariant is (Z) for every node . The search-tree order gives , where the dot joins lists. By (Z), SIZE for every , nil included (line L13).
Lemma 1 (UPDATE and rotations keep (Z)). If (Z) holds at the children of , line L14 makes it hold at . A rotation (lines L15 and L16) changes the children only of the two nodes and it moves; it calls UPDATE first on , which is now the child of and whose children have right sizes, and then on . So (Z) holds at both, and at every other node, whose subtree has the same node set as before.
Proof. for any node. A rotation changes only the links of and ; any other node keeps its children and its subtree, and the subtree of the top keeps the same node set.
Lemma 2 (updates keep (Z)). Insertion and deletion are those of the left-leaning red-black tree, with rotations as in Lemma 1 and with UPDATE at the end of FIX-UP (line L17). If (Z) holds before an update, it holds after.
Proof. The recursive procedures PUT, REMOVE and DELETE-MIN change the tree only by rotations, color flips, by replacing a child pointer of the current node with the result of a recursive call, by making a new node of size 1, by copying a key, and by returning nil for a removed leaf. Flips and key copies do not change any subtree's node set. Rotations keep (Z) by Lemma 1. By induction on the depth of the recursion, each recursive call returns a subtree in which (Z) holds; at that point, only may have a wrong size, since its child pointer changed. Each such procedure ends with FIX-UP, whose rotations keep (Z) in the subtrees they touch, and whose last step, line L17, recomputes the size of the node it returns from its children. So (Z) holds in the returned subtree. The rotations of MOVE-RED-LEFT and MOVE-RED-RIGHT happen before the recursive call, when (Z) holds everywhere, and keep it by Lemma 1.
Lemma 3 (SELECT). If (Z) holds and , SELECT returns .
Proof. Invariant at line L3: is a node, , and is the wanted key. It holds at the start. Let (line L3). By , entry is if (line L4), entry of if (line L5), and entry of if (line L6). In the last two cases the new is at least 0 and less than the size of the new , which is therefore not nil. Each step goes one level down, so the loop stops.
Lemma 4 (RANK). If (Z) holds, RANK returns the number of keys of less than , for any .
Proof. Invariant at line L8: the answer is plus the number of keys less than in the subtree of (with 0 for nil). At the start and is the root. If , no key of or its right subtree is less than , so the answer is plus the count in (line L9). If , the keys less than below are those of , so the answer is (line L10). If , all of and itself are less than , so the answer is plus the count in (line L11). When is nil, the answer is (line L12). Each step goes one level down.
Theorem. Starting from the empty tree, after any sequence of insertions and deletions, the tree is a valid left-leaning red-black tree with the right key set and with (Z), and SELECT and RANK return the key of a given rank and the rank of a given key.
Proof. The empty tree satisfies (Z) vacuously. The left-leaning red-black tree page proves that the updates keep the red-black rules and the key set; the size field does not affect any of their tests. Lemma 2 keeps (Z), and Lemmas 3 and 4 give the queries.