Doh, found this on wikipedia, much better than my silly pseudocode.
Search
The root of a B+ Tree represents the whole range of values in the tree, where every internal node a subinterval.
We are looking for a value k in the B+ Tree. Starting from the root, we are looking for the leaf which may contain the value k. At each node, we figure out which internal pointer we should follow. An internal B+ Tree node has at most d ≤ b children, where every one of them represents a different sub-interval. We select the corresponding node by searching on the key values of the node.
Function: search (k)
return tree_search (k, root);
Function: tree_search (k, node)
if node is a leaf then
return node;
switch k do
case k < k_0
return tree_search(k, p_0);
case k_i ≤ k < k_{i+1}
return tree_search(k, p_i);
case k_d ≤ k
return tree_search(k, p_d);
This pseudocode assumes that no duplicates are allowed.
Insertion
Perform a search to determine what bucket the new record should go into.
If the bucket is not full (at most b - 1 entries after the insertion), add the record.
Otherwise, split the bucket.
Allocate new leaf and move half the bucket's elements to the new bucket.
Insert the new leaf's smallest key and address into the parent.
If the parent is full, split it too.
Add the middle key to the parent node.
Repeat until a parent is found that need not split.
If the root splits, create a new root which has one key and two pointers.
B-trees grow at the root and not at the leaves.
Deletion
Start at root, find leaf L where entry belongs.
Remove the entry.
If L is at least half-full, done!
If L has fewer entries than it should,
Try to re-distribute, borrowing from sibling (adjacent node with same parent as L).
If re-distribution fails, merge L and sibling.
If merge occurred, must delete entry (pointing to L or sibling) from parent of L.
Merge could propagate to root, decreasing height.