1- //! A B-Tree based associative map.
2- //! This is a workhorse for most ordered map use cases. B-Trees are extremely
3- //! cache-friendly due to their high branching factor, making them faster than
4- //! binary search trees for larger datasets.
1+ //! A B-tree based associative map with configurable branching factor.
2+ //!
3+ //! B-trees are self-balancing tree data structures that maintain sorted data and allow
4+ //! searches, sequential access, insertions, and deletions in logarithmic time. They are
5+ //! optimized for systems that read and write large blocks of data.
6+ //!
7+ //! ## Complexity
8+ //! - Insert: O(log n)
9+ //! - Remove: O(log n)
10+ //! - Search: O(log n)
11+ //! - Space: O(n)
12+ //!
13+ //! ## Use Cases
14+ //! - Large datasets where cache efficiency matters
15+ //! - Ordered key-value storage with frequent range queries
16+ //! - Database indices and file systems
517//!
618//! ## Thread Safety
719//! This data structure is not thread-safe. External synchronization is required
1325
1426const std = @import ("std" );
1527
28+ /// Creates a B-tree map type with the specified key type, value type, comparison function,
29+ /// and branching factor.
30+ ///
31+ /// ## Parameters
32+ /// - `K`: The key type. Must be comparable via the `compare` function.
33+ /// - `V`: The value type.
34+ /// - `compare`: Function that compares two keys and returns their ordering.
35+ /// - `BRANCHING_FACTOR`: Number of children per node (must be >= 3). Higher values
36+ /// improve cache efficiency but use more memory per node. Typical values: 4-16.
37+ ///
38+ /// ## Example
39+ /// ```zig
40+ /// fn i32Compare(a: i32, b: i32) std.math.Order {
41+ /// return std.math.order(a, b);
42+ /// }
43+ /// var map = BTreeMap(i32, []const u8, i32Compare, 4).init(allocator);
44+ /// ```
1645pub fn BTreeMap (
1746 comptime K : type ,
1847 comptime V : type ,
@@ -36,21 +65,32 @@ pub fn BTreeMap(
3665 allocator : std.mem.Allocator ,
3766 len : usize = 0 ,
3867
68+ /// Creates a new empty B-tree map.
69+ ///
70+ /// The map must be deinitialized with `deinit()` to free allocated memory.
3971 pub fn init (allocator : std.mem.Allocator ) Self {
4072 return .{ .allocator = allocator };
4173 }
4274
4375 /// Returns the number of elements in the map.
76+ ///
77+ /// Time complexity: O(1)
4478 pub fn count (self : * const Self ) usize {
4579 return self .len ;
4680 }
4781
82+ /// Frees all memory used by the map.
83+ ///
84+ /// After calling this, the map is no longer usable. All references to keys
85+ /// and values become invalid.
4886 pub fn deinit (self : * Self ) void {
4987 self .clear ();
5088 self .* = undefined ;
5189 }
5290
53- /// Removes all elements from the map.
91+ /// Removes all elements from the map while keeping the allocated structure.
92+ ///
93+ /// Time complexity: O(n)
5494 pub fn clear (self : * Self ) void {
5595 if (self .root ) | r | self .deinitNode (r );
5696 self .root = null ;
@@ -82,7 +122,18 @@ pub fn BTreeMap(
82122 return compare (key_as_context , item );
83123 }
84124
85- /// Retrieves a pointer to the value associated with `key`.
125+ /// Retrieves an immutable pointer to the value associated with the given key.
126+ ///
127+ /// Returns `null` if the key does not exist in the map.
128+ ///
129+ /// Time complexity: O(log n)
130+ ///
131+ /// ## Example
132+ /// ```zig
133+ /// if (map.get(42)) |value| {
134+ /// std.debug.print("Value: {}\n", .{value.*});
135+ /// }
136+ /// ```
86137 pub fn get (self : * const Self , key : K ) ? * const V {
87138 var current = self .root ;
88139 while (current ) | node | {
@@ -97,7 +148,19 @@ pub fn BTreeMap(
97148 return null ;
98149 }
99150
100- /// Retrieves a mutable pointer to the value associated with `key`.
151+ /// Retrieves a mutable pointer to the value associated with the given key.
152+ ///
153+ /// Returns `null` if the key does not exist. The returned pointer can be used
154+ /// to modify the value in place without re-inserting.
155+ ///
156+ /// Time complexity: O(log n)
157+ ///
158+ /// ## Example
159+ /// ```zig
160+ /// if (map.getPtr(42)) |value_ptr| {
161+ /// value_ptr.* += 10; // Modify in place
162+ /// }
163+ /// ```
101164 pub fn getPtr (self : * Self , key : K ) ? * V {
102165 var current = self .root ;
103166 while (current ) | node | {
@@ -112,12 +175,25 @@ pub fn BTreeMap(
112175 return null ;
113176 }
114177
115- /// Returns true if the map contains the given key.
178+ /// Checks whether the map contains the given key.
179+ ///
180+ /// Time complexity: O(log n)
116181 pub fn contains (self : * const Self , key : K ) bool {
117182 return self .get (key ) != null ;
118183 }
119184
120- /// Inserts a key-value pair. If the key exists, the value is updated.
185+ /// Inserts a key-value pair into the map. If the key already exists, updates its value.
186+ ///
187+ /// Time complexity: O(log n)
188+ ///
189+ /// ## Errors
190+ /// Returns `error.OutOfMemory` if allocation fails.
191+ ///
192+ /// ## Example
193+ /// ```zig
194+ /// try map.put(1, "one");
195+ /// try map.put(1, "ONE"); // Updates the value
196+ /// ```
121197 pub fn put (self : * Self , key : K , value : V ) ! void {
122198 var root_node = if (self .root ) | r | r else {
123199 const new_node = try self .createNode ();
@@ -233,6 +309,18 @@ pub fn BTreeMap(
233309 }
234310 }
235311
312+ /// Removes a key-value pair from the map and returns the value.
313+ ///
314+ /// Returns `null` if the key does not exist.
315+ ///
316+ /// Time complexity: O(log n)
317+ ///
318+ /// ## Example
319+ /// ```zig
320+ /// if (map.remove(42)) |value| {
321+ /// std.debug.print("Removed value: {}\n", .{value});
322+ /// }
323+ /// ```
236324 pub fn remove (self : * Self , key : K ) ? V {
237325 if (self .root == null ) return null ;
238326 const old_len = self .len ;
0 commit comments