Proofs: BST floor and ceiling
These are the human proofs of BST floor and ceiling, at full length.
BST floor and ceiling return the largest key at most k and the smallest key at least k full
This proof shows: correctness, termination.
Let be a binary search tree with root and distinct keys, with the strict binary search tree property, and let be a key. For a node (or NIL) write for the set of keys in the subtree rooted at , with . For a finite set of keys, write , with $f(A) = $ NIL when no element of is at most . Treat NIL as smaller than each key, so that . Then for all finite .
We prove that FLOOR returns . The proof for CEILING is the same with the order reversed.
Invariant. Before each test of line L2:
where $\mathrm{key}(\mathrm{NIL}) = $ NIL.
Initialization. Before the first test, $best = $ NIL and , so the right side is .
Maintenance. Suppose (I) holds, $x \ne $ NIL, and line L3 does not return, so . Write and , so , and by the BST property each key of is less than and each key of is greater.
- Case (line L4). Each key in is at least , so $f({x.key} \cup R) = $ NIL, and . Line L4 sets to and leaves alone, so (I) holds after the step.
- Case (line L5). Then , and each key of is less than , so and . Hence . Also if $best \ne $ NIL: by Lemma A below, is a proper ancestor of at which the path went right, so is in its right subtree and . So
and after line L5 sets and , the right side of (I) is , the same value. So (I) holds.
Lemma A. At each test of line L2 with $best \ne $ NIL, is a proper ancestor of (or is NIL below it), and lies in the right subtree of .
Proof. changes only in line L5, where it becomes the current node and becomes its right child. Each later step moves to a child of , so stays in the subtree of that right child.
Termination. Each step moves from a node of depth to a child of depth or to NIL. The depth of a node is at most , so after at most steps is NIL or line L3 has returned.
The answer. If line L3 returns , then , and no key at most is larger than , so . If the loop ends, then $x = $ NIL and $f(D(x)) = $ NIL, so by (I) , which line L6 returns. The algorithm writes only the local variables and , so does not change.