Algorithm Search⌘K

Proofs: B*-tree

These are the human proofs of B*-tree, at full length.

Search, insert and delete keep the B*-tree properties and give the right answers full

This proof shows: correctness, termination.

We use the pseudocode of the page, a capacity C≥4C \ge 4, f=⌊(2C+1)/3⌋f = \lfloor (2C+1)/3 \rfloor and R=2f−1R = 2f - 1. The keys are distinct. The entries e(x)e(x) of a node xx are its keys if xx is a leaf and its children if xx is internal. A tree is valid if (S1) to (S4) of the page hold, with (S2) in the form: for an internal node xx with separators key[1..m]key[1..m], key[0]=−∞key[0] = -\infty, key[m+1]=+∞key[m+1] = +\infty, every key in the leaves below x.c[i]x.c[i] lies in [key[i],key[i+1])[key[i], key[i+1]), and the separators of each node are increasing.

Two facts about ff. (a) 3f≤2C+13f \le 2C + 1, by the definition of ff. (b) f≥3f \ge 3, because C≥4C \ge 4 gives 2C+1≥92C + 1 \ge 9. By (S1) and (b), each internal node other than the root has at least 3 children. Also f≤Cf \le C, since 3f≤2C+1<3C+33f \le 2C + 1 < 3C + 3, and R=2f−1≥fR = 2f - 1 \ge f.

Lemma 1 (search). In a valid tree, lines L1 to L5 reach the only leaf whose key range contains kk, so SEARCH returns true exactly when kk is a key. The range query returns the keys of [a,b][a, b] in order.

Proof. At each internal node, line L3 picks the child ii with key[i]≤k<key[i+1]key[i] \le k < key[i+1], and by (S2) no other child can hold kk. The loop goes one level down per step and stops at a leaf by (S3). The range query is the one of the B+ tree: every leaf to the left of the leaf of aa holds only keys below aa, and by (S4) the nextnext links visit the leaves in key order. □\square

Lemma 2 (SHARE). Let xx be an internal node, let x.c[j],…,x.c[j+g−1]x.c[j], \ldots, x.c[j+g-1] be valid subtrees of one height that satisfy (S2) with respect to the separators of xx, and let tt be their total number of entries, with t≥kt \ge k. After SHARE(x,j,g,k)(x, j, g, k):

  1. the keys in the leaves below xx are the same, and the leaf chain is in key order;
  2. the gg children are replaced by kk children of the same height, each with ⌊t/k⌋\lfloor t/k \rfloor or ⌈t/k⌉\lceil t/k \rceil entries, and xx gains k−gk - g children;
  3. (S2) holds at xx and inside each new child, and all leaves keep their depth.

Proof. Leaves. Line L17 concatenates the keys of the gg leaves. They are in increasing order, since each leaf is sorted and, by (S2), each key of a leaf is below the separator that follows it in xx, and each key of the next leaf is at least that separator. Line L18 cuts this sorted list into kk consecutive pieces of the stated sizes. Line L19 takes as the separator before each piece after the first its first key ss. Every key of the piece to the left is <s< s and every key of the piece is ≥s\ge s, and the outer bounds of the group, x.key[j]x.key[j] and x.key[j+g]x.key[j+g], do not change. So (S2) holds at xx. Line L20 links the pieces in order and gives the last one the old nextnext link of the group, so the chain stays in key order.

Internal nodes. Line L17 forms the sequence c1,s1,c2,s2,…,st−1,ctc_1, s_1, c_2, s_2, \ldots, s_{t-1}, c_t of the tt grandchildren of xx in the group and the separators between them: the separators of the group nodes and, between two group nodes, the separator of xx that divided them. By (S2) at xx and at the group nodes, every key below cpc_p lies in [sp−1,sp)[s_{p-1}, s_p), with s0=x.key[j]s_0 = x.key[j] and st=x.key[j+g]s_t = x.key[j+g]. Line L18 cuts the sequence of children into kk consecutive pieces. A new node gets the children of its piece and the separators between them, and the separator sps_p between the last child of one piece and the first of the next goes up to xx. Every grandchild keeps the same two separators as its bounds, one in its new parent or in xx, so (S2) holds at every level. No grandchild moves to another depth.

In both cases the sizes are as in item 2. □\square

Lemma 3 (insert below a node). Let the subtree of xx be valid except that xx may have any number of entries, and let kk be a key not in it. After INSERT-REC(x,k)(x, k), the subtree holds its old keys and kk, satisfies (S2) to (S4), every node below xx other than xx has ff to CC entries, and xx has gained at most one entry.

Proof. By induction on the height of xx. A leaf gains the one key kk in order (line L9). For an internal xx, line L10 picks the child c=x.c[i]c = x.c[i] whose range contains kk, so the new key respects (S2) at xx. By the hypothesis, after line L11 the child cc has between ff and C+1C + 1 entries and the nodes below it are fine. If it has at most CC, line L12 returns and xx has not changed its number of entries. Otherwise e(c)=C+1e(c) = C + 1. Each internal node other than the root has at least 3 children, and the root, being internal, has at least 2, so cc has a sibling next to it.

  • Line L14: a sibling yy next to cc has f≤e(y)≤C−1f \le e(y) \le C - 1. Then t=e(c)+e(y)t = e(c) + e(y) satisfies C+1+f≤t≤2CC + 1 + f \le t \le 2C. By Lemma 2 with k=2k = 2, each new node has at most ⌈2C/2⌉=C\lceil 2C / 2 \rceil = C and at least ⌊(C+1+f)/2⌋≥f\lfloor (C + 1 + f)/2 \rfloor \ge f entries, because C+1≥fC + 1 \ge f. The number of children of xx does not change.
  • Line L16: every sibling next to cc is full, and yy is one of them, so t=2C+1t = 2C + 1. By Lemma 2 with k=3k = 3, each new node has at least ⌊(2C+1)/3⌋=f\lfloor (2C+1)/3 \rfloor = f entries and at most ⌈(2C+1)/3⌉≤C\lceil (2C+1)/3 \rceil \le C, since 2C+1≤3C2C + 1 \le 3C. Now xx has one more child.

In both cases Lemma 2 gives (S2) to (S4). □\square

Theorem 1 (insert). If TT is valid and kk is not a key, after BSTAR-INSERT(T,k)(T, k) the tree is valid and its keys are the old keys and kk.

Proof. By Lemma 3 at the root, only the root can break (S1), and it has at most R+1R + 1 entries. If it has at most RR, the tree is valid: an internal root keeps at least 2 children, because no step removes a child. If it has R+1=2fR + 1 = 2f entries, line L8 puts a new root above it and calls SHARE with g=1g = 1 and k=2k = 2. By Lemma 2 the two new children have ff entries each, which is between ff and CC. The new root has 2 children, at most RR since R≥3R \ge 3, and all leaves are one level deeper, so (S3) holds. □\square

Lemma 4 (delete below a node). Let the subtree of xx be valid except that xx may have any number of entries, and let kk be a key in it. After DELETE-REC(x,k)(x, k), the subtree holds its old keys without kk, satisfies (S2) to (S4), every node below xx other than xx has ff to CC entries, and xx has lost at most one entry.

Proof. By induction on the height. A leaf loses kk (line L23). For internal xx, line L24 picks the only child c=x.c[i]c = x.c[i] that can hold kk, by Lemma 1, and after line L25 cc has between f−1f - 1 and CC entries by the hypothesis. If it has at least ff, line L26 returns. Otherwise e(c)=f−1e(c) = f - 1.

  • Line L27: a sibling yy next to cc has e(y)≥f+1e(y) \ge f + 1. Then 2f≤t≤f−1+C2f \le t \le f - 1 + C, and the two new nodes have at least ff and at most ⌈(f−1+C)/2⌉≤C\lceil (f - 1 + C)/2 \rceil \le C entries, since f≤Cf \le C. The number of children of xx does not change.
  • Line L28: xx has 2 children. By fact (b), xx is the root. The other child has exactly ff entries, since line L27 did not apply, so t=2f−1=Rt = 2f - 1 = R. SHARE with k=1k = 1 makes one child with RR entries, and xx loses one entry.
  • Lines L29 and L30: xx has at least 3 children, so there is a group of three neighbouring children that contains cc. Each sibling of cc next to it has exactly ff entries, since line L27 did not apply, and the third node has between ff and CC. So 3f−1≤t≤(f−1)+f+C3f - 1 \le t \le (f - 1) + f + C. If t≤2Ct \le 2C, the two new nodes have at most CC and at least ⌊(3f−1)/2⌋≥f\lfloor (3f - 1)/2 \rfloor \ge f entries, because 3f−1≥2f3f - 1 \ge 2f when f≥1f \ge 1, and xx loses one child. If t>2Ct > 2C, the three new nodes have at least ⌊(2C+1)/3⌋=f\lfloor (2C + 1)/3 \rfloor = f entries and at most ⌈t/3⌉≤C\lceil t/3 \rceil \le C, because t≤2f−1+C≤3Ct \le 2f - 1 + C \le 3C; the number of children of xx does not change.

Lemma 2 gives (S2) to (S4) in each case. □\square

Theorem 2 (delete). If TT is valid and kk is a key, after BSTAR-DELETE(T,k)(T, k) the tree is valid and its keys are the old keys without kk.

Proof. By Lemma 4 at the root, every node other than the root satisfies (S1), and the root has lost at most one entry, so it has at most RR. If the root is internal and now has one child, which happens only through line L28, that child has exactly RR entries and line L22 makes it the root. All leaves move one level up, so (S3) holds, and the new root has at most RR entries, and at least 2 children if it is internal, since R=2f−1≥2R = 2f - 1 \ge 2. Otherwise the root keeps at least 2 children. □\square

Termination. INSERT-REC and DELETE-REC go one level down per call, and SEARCH one level per loop step, so each operation makes at most h+1h + 1 calls, where hh is the height. Each SHARE does work linear in the size of its group. The range query visits each leaf at most once, because the nextnext links go strictly to the right. ■\blacksquare

Back to B*-tree