Root
Internal
Leaf (records)
1
STRUCT Node:
bool leaf
keys[] // leaf: record keys; internal: separator keys
children[] // only for internal nodes
parent
FUNCTION INSERT(tree, k):
L ← FIND_LEAF(tree.root, k)
INSERT_IN_LEAF(L, k)
IF |L.keys| ≤ 3: return
SPLIT_LEAF(L) // may cascade up
FUNCTION FIND_LEAF(x, k):
WHILE x is internal:
// choose smallest i with k < x.keys[i]; else take last child
i ← LOWER_BOUND(x.keys, k)
x ← x.children[i]
RETURN x
FUNCTION INSERT_IN_LEAF(L, k):
i ← LOWER_BOUND(L.keys, k)
INSERT L.keys at position i value k
FUNCTION SPLIT_LEAF(L): // 4 keys → 2|2
leftKeys ← L.keys[0..1] // two keys
rightKeys ← L.keys[2..3] // two keys
R ← new leaf with keys = rightKeys
L.keys ← leftKeys
sep ← R.keys[0] // separator promoted to parent
IF L is root:
P ← new internal node
P.keys ← [sep]
P.children ← [L, R]
set parents; tree.root ← P
RETURN
// insert R as L's right sibling in parent
P ← L.parent
j ← index of L in P.children
INSERT P.children at (j+1) value R
INSERT P.keys at j value sep
R.parent ← P
IF |P.children| ≤ 4: RETURN
SPLIT_INTERNAL(P) // may cascade up
FUNCTION SPLIT_INTERNAL(M): // 5 children → split 3|2 and promote
// children: C0 C1 C2 C3 C4; keys: K1 K2 K3 K4 (Ki separates Ci-1 & Ci)
leftChildren ← [C0, C1, C2]
rightChildren ← [C3, C4]
promote ← K3 // first key of right part
leftKeys ← [K1, K2]
rightKeys ← [K4]
// rewire
L ← M // reuse M as left node
R ← new internal node
L.children ← leftChildren; L.keys ← leftKeys
R.children ← rightChildren; R.keys ← rightKeys
set parents of rightChildren to R
IF M was root:
P ← new internal node
P.keys ← [promote]
P.children ← [L, R]
set parents; tree.root ← P
RETURN
// insert R into parent
P ← M.parent
j ← index of L in P.children
INSERT P.children at (j+1) value R
INSERT P.keys at j value promote
R.parent ← P
IF |P.children| > 4: SPLIT_INTERNAL(P)
FUNCTION LOWER_BOUND(a[], k):
// returns smallest i with a[i] ≥ k, else a.length
lo ← 0; hi ← |a|
WHILE lo < hi:
mid ← (lo + hi) // 2
IF a[mid] < k: lo ← mid + 1
ELSE: hi ← mid
RETURN lo