Proofs: Radix tree
These are the human proofs of Radix tree, at full length.
The radix tree operations keep the invariant and answer the string symbol table queries full
This proof shows: correctness.
We use the pseudocode and the invariant (R1) to (R4) of the page. For a node , is the concatenation of the labels from the root to . Each node other than the root has a parent , and for the edge from to , with by (R1). So strictly increases down each path.
Lemma 1 (uniqueness and walk). Under (R1), for each string at most one node has . The loop of lines L1 to L5 returns at line L4 if no node has , and it ends at that node otherwise.
Proof. Suppose with . Let be their lowest common ancestor. Since grows strictly down a path, neither node is an ancestor of the other, so has two distinct children on the paths to and . Both labels are nonempty and both are followed in at position , so they start with the same symbol , which (R1) forbids. For the walk: the loop keeps "". At a node , a node below with must lie below the child edge whose label starts with ; by (R1) that is at most the edge of line L3. If is NIL, no node lies below on the way to . If is not a prefix of , then is not a prefix of , and neither is the of any node below , since all of them extend . In both cases no node has . Else line L5 moves to with . The quantity drops by at least 1 each round, so the loop ends.
GET. By Lemma 1 and (R2), line L6 returns the value of if is a key, and NIL otherwise (no node, or a node with no value).
PUT. The loop keeps ", the invariant (R1) holds, and the multiset of keys and values is the old one". Line L10: no edge from starts with , so the new edge keeps (R1); the new leaf has and value , and was not a key, since by Lemma 1 no node had (that node would lie below an edge of starting with ). So (R2) and (R4) hold, and (R3) holds because the new node has a value. Line L11: starts with , so . If , lines L13 and L14 replace the edge with label by the edges with label and with label . Both labels are nonempty, the first starts with the same symbol as , and has one edge, so (R1) holds. The of each old node is the same, so the keys are the same. The new node has no value and one child, so (R3) fails at only. Line L15 moves to the child with . We show that the same call repairs . If , the loop ends with , and line L17 gives a value. Else , by the choice of as the longest common prefix, so the next round finds no edge of starting with and line L10 adds a second edge to . If , no split is done and the walk goes on. When the loop ends without line L10, is the node with . Lines L16 and L17 give it the value and count it if it had no value, so (R2) and (R4) hold, and (R3) holds at since it has a value.
DELETE. If line L19 returns, is not a key by Lemma 1 and (R2), and nothing changes. Else line L20 removes the value of the node with and updates the count, so (R2) and (R4) hold for the keys without . Now (R3) can fail only at . Two cases.
- has no edge. If is the root, (R3) asks nothing. Else line L21 removes the leaf , which has no value, so no key is lost. Its parent lost one child. If is not the root and has no value, then before the removal had at least two children by (R3), so it has at least one now. If it has two or more, (R3) holds. If it has exactly one, line L22 merges it as in the next case.
- has exactly one edge , is not the root, and has no value. Let be the edge from the parent of to . Line L22 replaces and by one edge from to with label . The new label starts with the first symbol of , so (R1) holds at . The of and of each node below it is unchanged, and the only removed node is , which has no value. So the keys are unchanged, and (R3) holds, since is gone and no other node lost a child.
- has two or more edges. Then (R3) holds at , and line L22 does nothing.
KEYS-WITH-PREFIX. Let be the query. Line L23 walks as in Lemma 1. If the walk ends exactly at a node , then . If ends inside the label of an edge to a child , so that , then each node with is or below : its path from the root shares the part up to the parent of , and by (R1) it then takes . In both cases, the nodes with are exactly the nodes of the subtree of the reached node . If the walk finds no edge, or a label that disagrees with before ends, then by the argument of Lemma 1 no node has with prefix , and the empty list is right. The stack holds pairs , because line L28 pushes . Each node of the subtree is pushed once. So by (R2), line L27 appends exactly the keys with prefix . The children are popped in increasing order of their first symbol, and by (R1) the first symbols differ, so the preorder lists the strings in lexicographic order, as in the proof for the trie.
Node bound. If (R3) holds and the tree has keys, then it has at most nodes. Proof. Each leaf other than the root has a value, so there are at most leaves, or the root alone. In a rooted tree, let , and be the numbers of nodes with zero, one, and two or more children. The tree has edges, and each edge goes to a child, so the number of edges is the sum of the numbers of children, which is at least . So , that is, . The nodes without a value other than the root have at least two children, so there are at most of them, and with the root and the at most nodes with values the total is at most .