A generic self-balancing binary search tree implementation that maintains balance using red-black coloring rules to ensure O(log n) operations.
import { RedBlackTree } from 'jsr:@mskr/data-structures';
const tree = new RedBlackTree<number>();
size: number
- Number of elements in the treeisEmpty(): boolean
- Whether the tree is empty
// Insert element - O(log n)
tree.insert(value);
// Remove element - O(log n)
const removed = tree.remove(value);
// Check if element exists - O(log n)
const exists = tree.contains(value);
// Get minimum element - O(log n)
const min = tree.min();
// Get maximum element - O(log n)
const max = tree.max();
// Remove all elements - O(1)
tree.clear();
// Convert to sorted array - O(n)
const array = tree.toArray();
// Iterate in sorted order
for (const value of tree) {
console.log(value);
}
const tree = new RedBlackTree<number>();
tree.insert(5);
tree.insert(3);
tree.insert(7);
console.log(tree.contains(3)); // true
console.log(tree.min()); // 3
console.log(tree.max()); // 7
// Iterate in sorted order
for (const value of tree) {
console.log(value); // 3, 5, 7
}
interface User {
id: number;
name: string;
}
const userTree = new RedBlackTree<User>({
comparator: (a, b) => a.id - b.id,
});
userTree.insert({ id: 1, name: 'Alice' });
userTree.insert({ id: 2, name: 'Bob' });
userTree.insert({ id: 3, name: 'Charlie' });
console.log(userTree.contains({ id: 2, name: 'Bob' })); // true
const tree = new RedBlackTree<number>({
initial: [5, 3, 7, 1, 4],
});
console.log(tree.min()); // 1
console.log(tree.max()); // 7
const names = new RedBlackTree<string>({
comparator: (a, b) => a.localeCompare(b),
});
names.insert('Charlie');
names.insert('Alice');
names.insert('Bob');
// Will iterate in alphabetical order
for (const name of names) {
console.log(name); // Alice, Bob, Charlie
}
class Product {
constructor(public id: number, public name: string, public price: number) {}
}
const products = new RedBlackTree<Product>({
comparator: (a, b) => {
// First compare by price
if (a.price !== b.price) {
return a.price - b.price;
}
// Then by id
return a.id - b.id;
},
});
try {
const empty = new RedBlackTree<number>();
empty.min(); // Throws EmptyStructureError
} catch (error) {
if (error instanceof EmptyStructureError) {
console.log('Tree is empty!');
}
}
- Insert: O(log n)
- Remove: O(log n)
- Contains: O(log n)
- Min/Max: O(log n)
- toArray: O(n)
- Space complexity: O(n)
The Red-Black Tree maintains the following properties to ensure balanced operations:
- Every node is either red or black
- The root is always black
- All leaves (NIL nodes) are black
- If a node is red, both its children are black
- Every path from root to leaves contains the same number of black nodes
- Generic type support
- Customizable element ordering through comparator function
- Optional initialization with existing values
- In-order traversal for sorted iteration
- Self-balancing for guaranteed O(log n) operations
- Type-safe implementation with full TypeScript support
The tree maintains balance through color adjustments and rotations:
- Left rotation: Used when right child becomes too heavy
- Right rotation: Used when left child becomes too heavy
- Color flips: Used to maintain red-black properties
- Recoloring during insert and delete operations
The tree supports flexible element comparison through:
- Default comparison using < and > operators
- Custom comparator function for complex objects
- Consistent handling of equality for duplicates