33//! This module provides a B+ tree data structure with a dictionary-like interface,
44//! supporting efficient insertion, deletion, lookup, and range queries.
55
6- use std :: ops :: { Bound , RangeBounds } ;
6+ // Range imports moved to range_queries.rs module
77
88// Import our new modules
99mod arena;
@@ -20,6 +20,8 @@ mod comprehensive_performance_benchmark;
2020mod node;
2121mod iteration;
2222mod validation;
23+ mod tree_structure;
24+ mod range_queries;
2325
2426pub use arena:: { Arena , ArenaStats , NodeId as ArenaNodeId , NULL_NODE as ARENA_NULL_NODE } ;
2527pub use compact_arena:: { CompactArena , CompactArenaStats } ;
@@ -30,7 +32,7 @@ pub use types::{BPlusTreeMap, NodeId, NodeRef, NULL_NODE, ROOT_NODE, LeafNode, B
3032pub use construction:: { InitResult as ConstructionResult } ;
3133pub use iteration:: { ItemIterator , FastItemIterator , KeyIterator , ValueIterator , RangeIterator } ;
3234
33- use std :: marker :: PhantomData ;
35+ // PhantomData import moved to tree_structure.rs module
3436
3537// Internal type imports removed - no longer needed in main lib.rs
3638
@@ -238,322 +240,15 @@ impl<K: Ord + Clone, V: Clone> BPlusTreeMap<K, V> {
238240 // OTHER API OPERATIONS
239241 // ============================================================================
240242
241- /// Returns the number of elements in the tree.
242- pub fn len ( & self ) -> usize {
243- self . len_recursive ( & self . root )
244- }
245-
246- /// Recursively count elements with proper arena access.
247- fn len_recursive ( & self , node : & NodeRef < K , V > ) -> usize {
248- match node {
249- NodeRef :: Leaf ( id, _) => self . get_leaf ( * id) . map ( |leaf| leaf. len ( ) ) . unwrap_or ( 0 ) ,
250- NodeRef :: Branch ( id, _) => self
251- . get_branch ( * id)
252- . map ( |branch| {
253- branch
254- . children
255- . iter ( )
256- . map ( |child| self . len_recursive ( child) )
257- . sum ( )
258- } )
259- . unwrap_or ( 0 ) ,
260- }
261- }
262-
263- /// Returns true if the tree is empty.
264- pub fn is_empty ( & self ) -> bool {
265- self . len ( ) == 0
266- }
267-
268- /// Returns true if the root is a leaf node.
269- pub fn is_leaf_root ( & self ) -> bool {
270- matches ! ( self . root, NodeRef :: Leaf ( _, _) )
271- }
272-
273- /// Returns the number of leaf nodes in the tree.
274- pub fn leaf_count ( & self ) -> usize {
275- self . leaf_count_recursive ( & self . root )
276- }
277-
278- /// Recursively count leaf nodes with proper arena access.
279- fn leaf_count_recursive ( & self , node : & NodeRef < K , V > ) -> usize {
280- match node {
281- NodeRef :: Leaf ( _, _) => 1 , // An arena leaf is one leaf node
282- NodeRef :: Branch ( id, _) => self
283- . get_branch ( * id)
284- . map ( |branch| {
285- branch
286- . children
287- . iter ( )
288- . map ( |child| self . leaf_count_recursive ( child) )
289- . sum ( )
290- } )
291- . unwrap_or ( 0 ) ,
292- }
293- }
294-
295- /// Clear all items from the tree.
296- pub fn clear ( & mut self ) {
297- // Clear all arenas and create a new root leaf
298- self . leaf_arena . clear ( ) ;
299- self . branch_arena . clear ( ) ;
300-
301- // Create a new root leaf
302- let root_leaf = LeafNode :: new ( self . capacity ) ;
303- let root_id = self . leaf_arena . allocate ( root_leaf) ;
304- self . root = NodeRef :: Leaf ( root_id, PhantomData ) ;
305- }
243+ // Tree structure operations moved to tree_structure.rs module
306244
307245 // Iterator methods moved to iteration.rs module
308246
309- /// Returns an iterator over key-value pairs in a range using Rust's range syntax.
310- ///
311- /// # Examples
312- ///
313- /// ```
314- /// use bplustree::BPlusTreeMap;
315- ///
316- /// let mut tree = BPlusTreeMap::new(16).unwrap();
317- /// for i in 0..10 {
318- /// tree.insert(i, format!("value{}", i));
319- /// }
320- ///
321- /// // Different range syntaxes
322- /// let range1: Vec<_> = tree.range(3..7).map(|(k, v)| (*k, v.clone())).collect();
323- /// assert_eq!(range1, vec![(3, "value3".to_string()), (4, "value4".to_string()),
324- /// (5, "value5".to_string()), (6, "value6".to_string())]);
325- ///
326- /// let range2: Vec<_> = tree.range(3..=7).map(|(k, v)| (*k, v.clone())).collect();
327- /// assert_eq!(range2, vec![(3, "value3".to_string()), (4, "value4".to_string()),
328- /// (5, "value5".to_string()), (6, "value6".to_string()),
329- /// (7, "value7".to_string())]);
330- ///
331- /// let range3: Vec<_> = tree.range(5..).map(|(k, v)| *k).collect();
332- /// assert_eq!(range3, vec![5, 6, 7, 8, 9]);
333- ///
334- /// let range4: Vec<_> = tree.range(..5).map(|(k, v)| *k).collect();
335- /// assert_eq!(range4, vec![0, 1, 2, 3, 4]);
336- ///
337- /// let range5: Vec<_> = tree.range(..).map(|(k, v)| *k).collect();
338- /// assert_eq!(range5, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
339- /// ```
340- pub fn range < R > ( & self , range : R ) -> RangeIterator < ' _ , K , V >
341- where
342- R : RangeBounds < K > ,
343- {
344- let ( start_info, skip_first, end_info) = self . resolve_range_bounds ( range) ;
345- RangeIterator :: new_with_skip_owned ( self , start_info, skip_first, end_info)
346- }
347-
348- /// Returns the first key-value pair in the tree.
349- pub fn first ( & self ) -> Option < ( & K , & V ) > {
350- self . items ( ) . next ( )
351- }
247+ // Range query operations moved to range_queries.rs module
352248
353- /// Returns the last key-value pair in the tree.
354- pub fn last ( & self ) -> Option < ( & K , & V ) > {
355- self . items ( ) . last ( )
356- }
357-
358- // ============================================================================
359- // RANGE QUERY HELPERS
360- // ============================================================================
361-
362- fn resolve_range_bounds < R > (
363- & self ,
364- range : R ,
365- ) -> (
366- Option < ( NodeId , usize ) > ,
367- bool ,
368- Option < ( K , bool ) > ,
369- )
370- where
371- R : RangeBounds < K > ,
372- {
373- // Optimize start bound resolution - eliminate redundant Option handling
374- let ( start_info, skip_first) = match range. start_bound ( ) {
375- Bound :: Included ( key) => ( self . find_range_start ( key) , false ) ,
376- Bound :: Excluded ( key) => ( self . find_range_start ( key) , true ) ,
377- Bound :: Unbounded => ( self . get_first_leaf_id ( ) . map ( |id| ( id, 0 ) ) , false ) ,
378- } ;
379-
380- // Avoid cloning end bound key when possible
381- let end_info = match range. end_bound ( ) {
382- Bound :: Included ( key) => Some ( ( key. clone ( ) , true ) ) ,
383- Bound :: Excluded ( key) => Some ( ( key. clone ( ) , false ) ) ,
384- Bound :: Unbounded => None ,
385- } ;
386-
387- ( start_info, skip_first, end_info)
388- }
389-
390- // ============================================================================
391- // RANGE QUERY OPTIMIZATION HELPERS
392- // ============================================================================
249+ // Range query helper methods moved to range_queries.rs module
393250
394- /// Find the leaf node and index where a range should start
395- fn find_range_start ( & self , start_key : & K ) -> Option < ( NodeId , usize ) > {
396- let mut current = & self . root ;
397-
398- // Navigate down to leaf level
399- loop {
400- match current {
401- NodeRef :: Leaf ( leaf_id, _) => {
402- let leaf = self . get_leaf ( * leaf_id) ?;
403-
404- // Use binary search instead of linear search for better performance
405- let index = match leaf. keys . binary_search ( start_key) {
406- Ok ( exact_index) => exact_index, // Found exact key
407- Err ( insert_index) => insert_index, // First key >= start_key
408- } ;
409-
410- if index < leaf. keys . len ( ) {
411- return Some ( ( * leaf_id, index) ) ;
412- } else if leaf. next != NULL_NODE {
413- // All keys in this leaf are < start_key, try next leaf
414- // Check if next leaf exists and has keys without redundant arena lookup
415- return Some ( ( leaf. next , 0 ) ) ;
416- } else {
417- // No more leaves
418- return None ;
419- }
420- }
421- NodeRef :: Branch ( branch_id, _) => {
422- let branch = self . get_branch ( * branch_id) ?;
423- let child_index = branch. find_child_index ( start_key) ;
424-
425- if child_index < branch. children . len ( ) {
426- current = & branch. children [ child_index] ;
427- } else {
428- return None ;
429- }
430- }
431- }
432- }
433- }
434-
435- /// Get the ID of the first (leftmost) leaf in the tree
436- fn get_first_leaf_id ( & self ) -> Option < NodeId > {
437- let mut current = & self . root ;
438-
439- loop {
440- match current {
441- NodeRef :: Leaf ( leaf_id, _) => return Some ( * leaf_id) ,
442- NodeRef :: Branch ( branch_id, _) => {
443- if let Some ( branch) = self . get_branch ( * branch_id) {
444- if !branch. children . is_empty ( ) {
445- current = & branch. children [ 0 ] ;
446- } else {
447- return None ;
448- }
449- } else {
450- return None ;
451- }
452- }
453- }
454- }
455- }
456-
457- // ============================================================================
458- // ENHANCED ARENA-BASED ALLOCATION FOR LEAF NODES
459- // ============================================================================
460-
461- // allocate_leaf method moved to insert_operations.rs module
462-
463- /// Deallocate a leaf node from the arena.
464- pub fn deallocate_leaf ( & mut self , id : NodeId ) -> Option < LeafNode < K , V > > {
465- self . leaf_arena . deallocate ( id)
466- }
467-
468- // Arena access methods moved to get_operations.rs module
469-
470- /// Get the number of free leaf nodes in the arena.
471- pub fn free_leaf_count ( & self ) -> usize {
472- self . leaf_arena . free_count ( )
473- }
474-
475- /// Get the number of allocated leaf nodes in the arena.
476- pub fn allocated_leaf_count ( & self ) -> usize {
477- self . leaf_arena . allocated_count ( )
478- }
479-
480- /// Get the leaf arena utilization ratio.
481- pub fn leaf_utilization ( & self ) -> f64 {
482- self . leaf_arena . utilization ( )
483- }
484-
485- // ============================================================================
486- // ARENA STATISTICS
487- // ============================================================================
488-
489- /// Get statistics for the leaf node arena.
490- pub fn leaf_arena_stats ( & self ) -> CompactArenaStats {
491- self . leaf_arena . stats ( )
492- }
493-
494- /// Get statistics for the branch node arena.
495- pub fn branch_arena_stats ( & self ) -> CompactArenaStats {
496- self . branch_arena . stats ( )
497- }
498-
499- /// Set the next pointer of a leaf node in the arena.
500- pub fn set_leaf_next ( & mut self , id : NodeId , next_id : NodeId ) -> bool {
501- self . get_leaf_mut ( id)
502- . map ( |leaf| {
503- leaf. next = next_id;
504- true
505- } )
506- . unwrap_or ( false )
507- }
508-
509- /// Get the next pointer of a leaf node in the arena.
510- // get_leaf_next method moved to get_operations.rs module
511-
512- // ============================================================================
513- // CHILD LOOKUP HELPERS (Phase 2)
514- // ============================================================================
515-
516- /// Find the child index and `NodeRef` for `key` in the specified branch,
517- /// returning `None` if the branch does not exist or index is out of range.
518- pub fn find_child ( & self , branch_id : NodeId , key : & K ) -> Option < ( usize , NodeRef < K , V > ) > {
519- self . get_branch ( branch_id) . and_then ( |branch| {
520- let idx = branch. find_child_index ( key) ;
521- branch. children . get ( idx) . cloned ( ) . map ( |child| ( idx, child) )
522- } )
523- }
524-
525- /// Mutable version of `find_child`.
526- pub fn find_child_mut ( & mut self , branch_id : NodeId , key : & K ) -> Option < ( usize , NodeRef < K , V > ) > {
527- self . get_branch_mut ( branch_id) . and_then ( |branch| {
528- let idx = branch. find_child_index ( key) ;
529- branch. children . get ( idx) . cloned ( ) . map ( |child| ( idx, child) )
530- } )
531- }
532-
533- // ============================================================================
534- // ENHANCED ARENA-BASED ALLOCATION FOR BRANCH NODES
535- // ============================================================================
536-
537- // allocate_branch method moved to insert_operations.rs module
538-
539- /// Deallocate a branch node from the arena.
540- pub fn deallocate_branch ( & mut self , id : NodeId ) -> Option < BranchNode < K , V > > {
541- self . branch_arena . deallocate ( id)
542- }
543-
544- // Branch arena access methods moved to get_operations.rs module
545-
546- /// Unsafe fast access to leaf node (no bounds checking)
547- /// SAFETY: Caller must ensure id is valid and allocated
548- pub unsafe fn get_leaf_unchecked ( & self , id : NodeId ) -> & LeafNode < K , V > {
549- self . leaf_arena . get_unchecked ( id)
550- }
551-
552- /// Unsafe fast access to branch node (no bounds checking)
553- /// SAFETY: Caller must ensure id is valid and allocated
554- pub unsafe fn get_branch_unchecked ( & self , id : NodeId ) -> & BranchNode < K , V > {
555- self . branch_arena . get_unchecked ( id)
556- }
251+ // All arena management and tree structure methods moved to tree_structure.rs module
557252
558253
559254
@@ -563,40 +258,7 @@ impl<K: Ord + Clone, V: Clone> BPlusTreeMap<K, V> {
563258
564259 // All validation and debugging methods moved to validation.rs module
565260
566- /// Count the number of leaf and branch nodes actually in the tree structure.
567- pub fn count_nodes_in_tree ( & self ) -> ( usize , usize ) {
568- if matches ! ( self . root, NodeRef :: Leaf ( _, _) ) {
569- // Single leaf root
570- ( 1 , 0 )
571- } else {
572- self . count_nodes_recursive ( & self . root )
573- }
574- }
575-
576- /// Recursively count nodes in the tree.
577- fn count_nodes_recursive ( & self , node : & NodeRef < K , V > ) -> ( usize , usize ) {
578- match node {
579- NodeRef :: Leaf ( _, _) => ( 1 , 0 ) , // Found a leaf
580- NodeRef :: Branch ( id, _) => {
581- if let Some ( branch) = self . get_branch ( * id) {
582- let mut total_leaves = 0 ;
583- let mut total_branches = 1 ; // Count this branch
584-
585- // Recursively count in all children
586- for child in & branch. children {
587- let ( child_leaves, child_branches) = self . count_nodes_recursive ( child) ;
588- total_leaves += child_leaves;
589- total_branches += child_branches;
590- }
591-
592- ( total_leaves, total_branches)
593- } else {
594- // Invalid branch reference
595- ( 0 , 0 )
596- }
597- }
598- }
599- }
261+ // Tree structure counting methods moved to tree_structure.rs module
600262
601263 // Validation helper methods moved to validation.rs module
602264
0 commit comments