๐ดโซ Red-Black Tree
Self-balancing binary search tree with guaranteed O(log n) operations
Overview
Implements a persistent red-black tree โ a self-balancing BST that maintains balance invariants through node coloring. Guarantees O(log n) for insert, delete, and lookup. All operations return new trees (functional/immutable).
Concepts Demonstrated
- Algebraic data types โ tree with color, left, key, value, right
- Pattern matching โ the elegant four-case balance function
- Invariant maintenance โ red-black properties preserved on mutation
- Persistent data structures โ path copying for immutability
- Polymorphic comparison โ generic key types
Red-Black Invariants
- Every node is red or black
- The root is always black
- No red node has a red child
- Every path from root to leaf has the same number of black nodes
These invariants guarantee the tree height is at most 2ยทlogโ(n+1), ensuring logarithmic operations.
The Balance Function
(* Okasaki's elegant four-case balance *)
let balance = function
| Black, Node(Red, Node(Red,a,x,b), y, c), z, d
| Black, Node(Red, a, x, Node(Red,b,y,c)), z, d
| Black, a, x, Node(Red, Node(Red,b,y,c), z, d)
| Black, a, x, Node(Red, b, y, Node(Red,c,z,d))
โ Node(Red, Node(Black,a,x,b), y, Node(Black,c,z,d))
| color, left, key, right
โ Node(color, left, key, right)
This single function handles all four rotation cases with pattern matching โ one of the most elegant examples of algebraic data types in action.
Key Functions
| Function | Description |
|---|---|
insert | Add a key-value pair, rebalancing as needed |
find | Look up a key (returns option) |
remove | Delete a key, maintaining balance |
mem | Check if a key exists |
min_binding / max_binding | Smallest/largest key |
fold / iter | In-order traversal |
of_list / to_list | Convert to/from sorted lists |