Generic counted B-tree with O(log n) indexed access, insert, delete, and range operations
Dependencies
moon add dowdiness/btreeInternal(counts=[5, 3, 4], total=12)
├── Leaf(elem=a, span=5) positions [0, 5)
├── Leaf(elem=b, span=3) positions [5, 8)
└── Leaf(elem=c, span=4) positions [8, 12)// Define your element type
struct TextRun {
text : String
len : Int
}
// Implement BTreeElem traits (HasLength, Spanning, Mergeable, Sliceable)
impl @rle.HasLength for TextRun with fn length(self) -> Int { self.len }
impl @rle.Spanning for TextRun with fn span(self) -> Int { self.len }
impl @rle.Mergeable for TextRun with fn can_merge(a : TextRun, b : TextRun) -> Bool {
true
}
impl @rle.Mergeable for TextRun with fn merge(a : TextRun, b : TextRun) -> TextRun {
{ text: a.text + b.text, len: a.len + b.len }
}
// ... plus Sliceable
impl @btree.BTreeElem for TextRun
// Use the tree
let tree : @btree.BTree[TextRun] = @btree.BTree::new()
tree.init_root({ text: "hello", len: 5 }, 5)| Method | Description | Complexity |
|---|---|---|
| BTree::new(min_degree?) | Create empty tree (default min_degree=10) | O(1) |
| get_at(pos) | Element at span position | O(log n) |
| find(pos) | Element + offset within element | O(log n) |
| mutate_for_insert(pos, callback) | Insert via leaf splice callback | O(k + log n) at fixed t |
| mutate_for_delete(pos, callback) | Delete via leaf splice callback | O(k + log n) at fixed t |
| delete_range(start, end) | Delete span range [start, end), with boundary repair/merge | O(log n) path planning/splice; O(n) repair worst case |
| normalize_boundary_at(pos) | Merge the complete mergeable closure around one exact leaf boundary | O((m + 1) log n) at fixed t |
| from_sorted(items, min_degree?) | Bulk-build from sorted (elem, span) pairs | O(n) |
| view(start?, end?) | Slice elements in range | O(k + log n) |
| iter() | Lazy cursor-based iterator | O(n) total |
| each(f) | Visit all elements | O(n) |
| to_array() | Collect all elements | O(n) |
| span() | Total span (cached) | O(1) |
| size() | Number of leaves | O(1) |
| Operation | Accepted bounds | Other input |
|---|---|---|
| find(pos), get_at(pos) | 0 <= pos < span() | Return None for an empty tree, a negative position, or pos >= span(). |
| mutate_for_insert(pos, callback) | A non-empty tree and 0 <= pos <= span(); the end position is valid. | Abort for an empty tree or a position outside the accepted bounds. Use init_root for the first element. |
| mutate_for_delete(pos, callback) | 0 <= pos < span() | Return None without calling the callback for an empty tree or an out-of-bounds position. |
| delete_range(start, end) | 0 <= start < end; end is clamped to span(). | No-op for an empty tree, a negative start, an empty or reversed range, or start >= span(). |
| normalize_boundary_at(pos) | 0 < pos < span(), where pos is an exact leaf boundary. | No-op for an empty tree, an outer or out-of-bounds position, a position inside a leaf, or a stable boundary. |
| view(start?, end?) | Defaults to [0, span()); a negative start clamps to 0, and an omitted or oversized end clamps to span(). | Return an empty array when the clamped range is empty or reversed, its end is negative, its start is at or beyond span(), or the tree is empty. |
| Shape | Replaced child interval | new_leaves |
|---|---|---|
| Insert before child i | [i, i) | [new] |
| Replace child i | [i, i + 1) | [replacement] |
| Delete child i | [i, i + 1) | [] |
| Split child i | [i, i + 1) | [left, right, ...] |
dowdiness/rle Traits: Spanning, Mergeable, Sliceable
↑
dowdiness/btree Counted B+ tree (this library)
↑
dowdiness/order-tree High-level API: insert_at, delete_at, from_arrayfn[T, R] BTree::mutate_for_delete(self : BTree[T], pos : Int, f : (LeafContext[T]) -> (Splice[T], R)) -> R?fn[T] BTree::mutate_for_insert(self : BTree[T], pos : Int, f : (LeafContext[T]) -> Splice[T]) -> Unitimpl Show for FindResult[T]pub(all) struct LeafContext[T] {
elem : T
span : Int
offset : Int
child_idx : Int
// private fields
} derive(Debug)Generic counted B-tree with O(log n) indexed access, insert, delete, and range operations
Dependencies