Proofs: Adaptive radix tree
These are the human proofs of Adaptive radix tree, at full length.
The adaptive radix tree operations keep the invariant and implement the symbol table full
This proof shows: correctness.
We use the representation, the invariant (A1) to (A3) and the pseudocode of the page. All keys, stored or queried, end with the terminator byte 0 and contain no other 0, so no key is a proper prefix of another. For a node , is the string of : the concatenation, from the root down to the parent of , of each inner node's prefix and the byte of the edge taken. Write . By (A1), every leaf below has a key that starts with , and if is inner, with .
Lemma 1 (layouts). FIND-CHILD(, ) returns the child of with byte or NIL; ADD-CHILD, REMOVE and the change of layout keep the set of (byte, child) pairs, except for the one pair added or removed.
Proof. In Node4 and Node16, the bytes and the children are parallel arrays, so the child of is at the index of . In Node48, the index array maps to the slot of its child or to . In Node256, the slot at holds the child or NIL. A change of layout reads all pairs of the old node and adds them to the new one.
Lemma 2 (search). Under (A1) to (A3), the walk of lines L1 to L4 on a key ends at the unique leaf whose key is if is stored, and otherwise at NIL or at some leaf.
Proof. Suppose is stored, at leaf . We show that the walk keeps the claim " is an ancestor of (or itself) and ". This holds at the root with . At an inner ancestor of , (A1) gives that starts with , so line L2 passes and line L3 sets . The child of on the way to has byte , because starts with the path of that child, and by Lemma 1 and the distinct bytes of (A2), FIND-CHILD returns it. Line L4 then sets to the depth of the child. The walk ends at a leaf, which must be . Uniqueness follows from (A3) and the fact that a map stores each key once (as shown for PUT below). If is not stored, any leaf reached has a different key.
GET. By Lemma 2, line L5 returns the value of exactly when is stored, because it compares the full key at the leaf.
PUT. If is stored, the walk reaches its leaf exactly as in Lemma 2, line L8 finds it and replaces the value, and the tree does not change otherwise. Assume now that is not stored. The walk of lines L8 to L17 keeps the claim of Lemma 2 for the prefix of it has matched so far: , and starts with . It ends in one of three ways.
- Lines L9 and L10, at a leaf . Its key starts with , as does , and . Neither is a prefix of the other, by the terminator, so they first differ at some position with , and the bytes and exist and differ. The new Node4 sits where was, so its path is ; its prefix is shared by both keys; its two children have distinct bytes. So (A1) holds for both leaves, and the new node has 2 children, so (A2) holds.
- Line L12, inside the prefix of an inner node . The keys below start with , and agrees with on its first bytes and then differs. The new Node4 takes the place of with prefix ; hangs below it at the byte with prefix , so the path string of every node below , through the new node, the byte and the shortened prefix, is unchanged; and the new leaf hangs at the byte . So (A1) and (A2) hold.
- Lines L14 to L16, at an inner node with no child for . If is full, its pairs are copied into the next larger layout (Lemma 1), which has room. The new leaf gets the byte , which no other child has, and its path is , a prefix of . So (A1) holds, and the count grows by one, staying in the range of the layout.
In each case one leaf is added, so (A3) holds with the new key counted. Line L17 moves to a child whose path is a prefix of , so the claim holds there. The walk ends because grows and is finite.
DELETE. If is not stored, line L19 returns without change, by Lemma 2. Otherwise the walk ends at the leaf of , and line L20 removes it from its parent , which removes exactly one key, so (A3) holds, and (A1) is unaffected for the other leaves. Now may break (A2).
- If has one child left (line L21), is replaced by . If is a leaf, its path becomes , which is a prefix of its old path, so (A1) still holds. If is inner, its new prefix is , where is its byte in , so is unchanged, and so are the paths of all nodes below . The parent of keeps the same number of children.
- If reaches its shrink threshold (line L22), its pairs move to the smaller layout, which has room for them, and by the choice of thresholds the count is in the range of the new layout.
- Otherwise keeps at least the lower end of its range, by the choice of thresholds, since its count fell by one from within its range and did not reach the threshold.
So (A1) to (A3) hold after the deletion.
Order. The walk over all leaves visits the children of each inner node in increasing byte order, by Lemma 1. Two keys in different subtrees of a node agree on and differ at the next byte, which is the byte of their edges, so the leaves come out in increasing byte order of their keys. Removing the terminator does not change the order, because it is the smallest byte and is the last byte of each key.