B-tree
A balanced search tree whose nodes hold several keys and children, with every leaf at the same depth; full nodes are split on the way down. Built for disks: height O(log_t n).
On a disk, reading a block is expensive but reading several keys from the same block is nearly free. So instead of a binary tree, nodes hold several keys and children, which keeps the tree (and the number of disk reads) short.
Read the full explanation ↓- Time:
O(t · log_t n) per insert - Space:
O(n) - CLRS, chapter 18
- Horowitz–Sahni, chapter 11
Ten keys into a B-tree with t = 2 (1 to 3 keys per node); the root splits twice and the tree reaches three levels.
class BNode:def __init__(self):self.keys = []self.children = []def btree(items):# Minimum degree t = 2: every node has 1 to 3 keys (a 2-3-4 tree).t = 2root = BNode()for k in items:if len(root.keys) == 2 * t - 1:new_root = BNode()new_root.children.append(root)root = new_rootsplit_child(root, 0, t)insert_nonfull(root, k, t)return root.keysdef insert_nonfull(node, k, t):while node.children:i = 0while i < len(node.keys) and k > node.keys[i]:i = i + 1child = node.children[i]if len(child.keys) == 2 * t - 1:split_child(node, i, t)if k > node.keys[i]:i = i + 1child = node.children[i]node = childi = 0while i < len(node.keys) and k > node.keys[i]:i = i + 1node.keys.insert(i, k)def split_child(x, i, t):# The full child y gives its middle key to x and its upper half to a new node z.y = x.children[i]z = BNode()middle = y.keys[t - 1]z.keys = y.keys[t:]y.keys = y.keys[: t - 1]if y.children:z.children = y.children[t:]y.children = y.children[:t]x.keys.insert(i, middle)x.children.insert(i + 1, z)
Start
∅
Local variables
Orange = changed in this step
items list
Call stack
- btree()line 7
Explanation
The idea
On a disk, reading a block is expensive but reading several keys from the same block is nearly free. So instead of a binary tree, nodes hold several keys and children, which keeps the tree (and the number of disk reads) short.
In a B-tree of minimum degree t:
- every node except the root holds between
t − 1and2t − 1keys; a node withkkeys hask + 1children; - the keys in a node are sorted, and child
iholds the keys between keyi−1and keyi; - all leaves are at the same depth.
Here t = 2 (a 2-3-4 tree).
Insertion (CLRS)
On the way down, each full node is split before we enter it: its middle key moves up to the parent and its upper half becomes a new node. Since the parent is never full, a split never has to travel back up. The tree only grows taller when the root splits, which is why all leaves stay at the same depth.
Deletion
Deletion uses the same idea (before entering a child, make sure it has at least t keys), borrowing from a sibling or
merging two nodes. Only insertion is shown here.