Algorithm Search⌘K

Proofs: 2-3-4 tree

These are the human proofs of 2-3-4 tree, at full length.

Top-down insertion and deletion keep the 2-3-4 tree valid full

This proof shows: correctness.

A tree is valid when (B1) each node has 1, 2 or 3 sorted keys, (B2) an internal node with jj keys has j+1j + 1 children, (B3) the keys are in search-tree order, so all keys of child cic_i lie strictly between the keys xi−1x_{i-1} and xix_i of the node (with x−1=−∞x_{-1} = -\infty and the last bound +∞+\infty), and (B4) all leaves are at the same depth. During a deletion we allow two exceptions for a moment: the root may hold no key and have one child (after a merge at the root), and a key may have two copies, as explained in Lemma 5. We write K(t)K(t) for the set of keys of the subtree tt.

Lemma 1 (SPLIT-CHILD). Let tt be a node with at most 2 keys whose child c=cic = c_i has the 3 keys a<b<da < b < d. Lines L10 and L11 give a valid tree with the same keys, the same depth of every leaf, and tt with one key more.

Proof. The new left node gets aa and the two left children of cc, the new right node gets dd and the two right children; each is a 2-node (or a leaf with one key), so (B1) and (B2) hold for them. The key bb goes into tt at position ii, and the two new nodes become children ii and i+1i + 1. Then tt has at most 3 keys and one more child than before, so (B1) and (B2) hold. All keys of the left node are less than bb and greater than xi−1x_{i-1}, and all keys of the right node are greater than bb and less than xix_i, so (B3) holds. Both new nodes are at the depth of cc, and the children of cc keep their depths, so (B4) holds. □\square

Lemma 2 (MERGE). Let tt have at least 2 keys, or be the root, and let cic_i and ci+1c_{i+1} be 2-nodes. Line L26 gives a valid tree with the same keys and leaf depths, in which cic_i is a 4-node and tt has one key less. If tt was the root with one key, it now has no key and the single child cic_i.

Proof. The node cic_i gets the keys aa, xix_i, dd with a<xi<da < x_i < d by (B3), and the four children of the two nodes in order. (B1) to (B3) hold for it, and the leaf depths do not change. The node tt loses one key and one child. □\square

Lemma 3 (FILL). Let tt have at least 2 keys, or be the root, and let cic_i be a 2-node. Lines L23 to L25 give a valid tree with the same keys and leaf depths, in which the child that holds the old key of cic_i and covers the same key range has at least 2 keys, and the returned index points to it.

Proof. At line L23 the left sibling s=ci−1s = c_{i-1} has at least 2 keys. Its last key yy goes up into position i−1i - 1 of tt, the old xi−1x_{i-1} goes down to the front of cic_i, and the last child of ss becomes the first child of cic_i. The keys of that child lie between yy and xi−1x_{i-1}, which are now the bounds of the first child slot of cic_i, so (B3) holds; the child keeps its depth. ss keeps at least 1 key and cic_i now has 2. Line L24 is the mirror image. At line L25 both siblings that exist are 2-nodes, and Lemma 2 merges cic_i with one of them into a 4-node, whose index is returned. In each case the keys that cic_i covered are covered by the returned child. □\square

Lemma 4 (INSERT). If the tree is valid and k∉Kk \notin K, INSERT gives a valid tree with keys K∪{k}K \cup \{k\}. If k∈Kk \in K, it gives a valid tree with keys KK.

Proof. If the root is nil, line L1 makes a leaf with one key. If the root is a 4-node, line L2 puts an empty root above it and splits it by Lemma 1; all leaves move down by one level together, so (B4) holds and the new root has one key.

Invariant. At each test of line L5, the tree is valid, its keys are KK, tt is not a 4-node, and if kk is in the tree or is to be placed, its place is in the subtree of tt: all keys of tt's subtree range contain kk by (B3).

It holds at the first test, since the root is not a 4-node after line L2. If kk is a key of tt, line L6 returns. If tt is a leaf, it has at most 2 keys, and line L7 inserts kk at the position that keeps it sorted; tt gets at most 3 keys, and (B3) holds because kk lies in the range of tt. Else let cic_i be the child whose range contains kk. If it is a 4-node, line L8 splits it by Lemma 1, which is allowed because tt is not a 4-node; the middle key goes into tt at position ii. If it equals kk, the line returns; else kk lies in the range of one of the two new children, and ii points to it. That child is a 2-node. If cic_i was not a 4-node, it is not one now. Line L9 steps down, and the invariant holds at the next test. Each step goes one level down, so the loop stops at a leaf. □\square

Lemma 5 (DELETE). If the tree is valid, DELETE gives a valid tree with keys K∖{k}K \setminus \{k\} for the key kk given.

Proof. Write k0k_0 for the key given. During the loop, kk is either k0k_0 or a replacement key, as explained below.

Invariant. At each test of line L14: (D1) the tree satisfies (B1) to (B4), except that the root may have no key and one child, and that in (B3) the two copies of kk of (D3) count as equal bounds; (D2) tt is the root or has at least 2 keys; (D3) either k=k0k = k_0 and the keys of the tree are KK, or k≠k0k \ne k_0, an ancestor of tt holds kk in the place of k0k_0, and a second copy of kk is the largest (or the smallest) key of the subtree of tt, in a leaf of it, so the keys are (K∖{k0})(K \setminus \{k_0\}) with kk counted twice; (D4) the range of tt contains kk.

It holds at the first test with tt the root. If tt is a leaf, line L15 removes kk if it is there. By (D2), tt keeps at least 1 key unless it is the root, which may become empty only when it held the last key of the tree. In the first case of (D3) the keys are now K∖{k0}K \setminus \{k_0\}, or KK when k0k_0 was absent. In the second case the duplicate copy of kk is gone, and the keys are K∖{k0}K \setminus \{k_0\}.

If tt is internal and holds kk at position ii (line L16), there are three cases. At line L17, cic_i has at least 2 keys. The largest key pp of its subtree is the predecessor of kk; writing pp over kk keeps (B3) in the sense of (D1), because pp is greater than all other keys of cic_i's subtree and less than the keys to the right. Now k←pk \leftarrow p and t←cit \leftarrow c_i, which has at least 2 keys and whose range contains pp, so (D2) to (D4) hold. From here on, pp is the largest key of the subtree of tt, so it is not a key of an internal node on the path, and the path follows the last child at each level. There, line L20 can only borrow from the left sibling, which moves a key of that sibling up, or merge with the left sibling, which moves a key of tt down; neither moves pp. So pp stays in the last leaf, line L16 does not find it again, and (D3) holds at each step. Line L18 is the mirror image, with the successor, the smallest key, and the first child at each level. At line L19 both children are 2-nodes, and tt has at least 2 keys or is the root, so Lemma 2 applies: kk moves down into the merged 4-node, and tt becomes that node.

If tt is internal and does not hold kk, the child cic_i whose range contains kk is reached. If it is a 2-node, line L20 makes the child that covers kk hold at least 2 keys, by Lemma 3, which applies by (D2). Line L21 steps down, and (D2) and (D4) hold.

Each step goes one level down, so the loop reaches a leaf. Line L22 removes an empty root and makes its only child the root; all leaves move up by one level together, so (B4) holds and (D1) gives a valid tree. If the tree held only k0k_0, the root was a leaf and becomes nil. □\square

Theorem. Starting from the empty tree, after any sequence of insertions and deletions the tree is a valid 2-3-4 tree that holds exactly the keys inserted and not deleted since. CONTAINS returns true exactly for these keys.

Proof. The empty tree is valid. Lemmas 4 and 5 keep it valid and give the stated key sets. CONTAINS follows (B3): at each node, the key can lie only in the child whose range contains it, and it stops at a leaf after at most hh steps. ■\blacksquare

Back to 2-3-4 tree