From a6291cb7b000aad52e657ebfbfc47610023c7e85 Mon Sep 17 00:00:00 2001 From: Saurav Maheshkar Date: Sun, 10 Aug 2025 21:58:29 +0100 Subject: [PATCH 1/3] mnt: improve traits --- src/lib.rs | 627 ++++++++++++------- src/tree.rs | 1676 ++++++++++++++++++++++----------------------------- 2 files changed, 1132 insertions(+), 1171 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 99d0fd5..8a9c3b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,8 +42,64 @@ use std::collections::{HashMap, HashSet, VecDeque}; use std::fmt; use std::hash::{Hash, Hasher}; +/// Core trait for any tree-like data structure +pub trait TreeLike { + /// Returns the total number of elements in the tree + fn size(&self) -> usize; + + /// Returns true if the tree contains no elements + fn is_empty(&self) -> bool; + + /// Search for a node by its value + fn search_by_value(&self, value: &T) -> Option + where + T: PartialEq; + + /// Returns the number of nodes in the subtree rooted at the given node + fn num_nodes(&self, node_id: Number) -> usize; + + /// Returns true if the subtree rooted at the given node is balanced + fn is_balanced(&self, node_id: Number) -> bool; +} + +/// Core trait for node-based tree data structures +pub trait NodeBasedTree: TreeLike { + /// Returns the ID of the root node, if any + fn root_id(&self) -> Option; + + /// Returns a reference to the node with the given ID, if it exists + fn get_node(&self, id: Number) -> Option<&Node>; + + /// Returns a mutable reference to the node with the given ID, if it exists + fn get_node_mut(&mut self, id: Number) -> Option<&mut Node>; + + /// Returns the height of the subtree rooted at the given node + fn height(&self, node_id: Number) -> usize; + + /// Returns the depth of the node with the given ID + fn depth(&self, node_id: Number) -> usize; + + /// Returns the number of leaf nodes in the subtree rooted at the given node + fn num_leaves(&self, node_id: Number) -> usize; + + /// Returns all leaf nodes in the subtree rooted at the given node + fn get_leaves(&self, node_id: Number) -> Vec<&Node>; + + /// Performs a depth-first search starting from the given node + fn dfs(&self, node_id: Number) -> Vec<&Node>; + + /// Performs a breadth-first search starting from the given node + fn bfs(&self, node_id: Number) -> Vec<&Node>; + + /// Performs a preorder traversal starting from the given node + fn preorder(&self, node_id: Number) -> Vec<&Node>; + + /// Performs a postorder traversal starting from the given node + fn postorder(&self, node_id: Number) -> Vec<&Node>; +} + pub mod tree; -pub use tree::{VEBTree, BST}; +pub use tree::{vEB, BST}; #[derive(Debug, Clone, Copy)] pub struct FloatId(f64); @@ -93,70 +149,27 @@ pub type Number = f64; /// Generic Node Struct /// -/// A flexible node structure that can represent various types of graph and tree nodes. -/// Each node has a unique ID and can maintain relationships with other nodes through -/// various connection types: undirected edges, directed edges, parent-child relationships, -/// and binary tree left-right relationships. -/// -/// # Examples -/// -/// ## Basic node creation and properties -/// -/// ``` -/// use jangal::Node; -/// -/// let node = Node::new("Hello, World!"); -/// assert_eq!(node.value, "Hello, World!"); -/// assert!(node.is_root()); -/// assert!(node.is_leaf()); -/// assert_eq!(node.num_children(), 0); -/// ``` -/// -/// ## Creating a node with a specific ID -/// -/// ``` -/// use jangal::Node; -/// -/// let node = Node::with_id(42, 100.0); -/// assert_eq!(node.value, 42); -/// assert_eq!(node.id, 100.0); -/// ``` -/// -/// ## Building relationships between nodes -/// -/// ``` -/// use jangal::Node; -/// -/// let mut parent = Node::new("parent"); -/// let mut child = Node::new("child"); -/// -/// // Create parent-child relationship -/// parent.add_child(child.id); -/// child.set_parent(parent.id); -/// -/// assert_eq!(parent.children(), vec![child.id]); -/// assert_eq!(child.parent(), Some(parent.id)); -/// assert!(!parent.is_leaf()); -/// assert!(!child.is_root()); -/// ``` +/// This node can be used to build various types of tree structures: +/// - General trees (using parent/children relationships) +/// - Binary trees (using left/right relationships) +/// - Graphs (using edges) +/// - BSTs (using both parent/children and left/right) #[derive(Debug, Clone)] #[allow(dead_code)] pub struct Node { pub value: T, pub id: Number, - // Undirected edges - edges: HashSet, + // General tree structure + parent: Option, + children: HashSet, - // Directed edges + // Graph structure + edges: HashSet, incoming: HashSet, outgoing: HashSet, - // Tree structure - parent: Option, - children: HashSet, - - // BST specific + // BST-specific structure (only used when building BSTs) left: Option, right: Option, } @@ -184,11 +197,11 @@ impl Node { Self { value, id: Self::generate_id(), + parent: None, + children: HashSet::new(), edges: HashSet::new(), incoming: HashSet::new(), outgoing: HashSet::new(), - parent: None, - children: HashSet::new(), left: None, right: None, } @@ -212,11 +225,11 @@ impl Node { Self { value, id, + parent: None, + children: HashSet::new(), edges: HashSet::new(), incoming: HashSet::new(), outgoing: HashSet::new(), - parent: None, - children: HashSet::new(), left: None, right: None, } @@ -539,7 +552,7 @@ impl Node { /// use jangal::Node; /// /// let mut root = Node::new(10); - /// let right = Node::new(15); + /// let right = Node::new(5); /// /// root.set_right(right.id); /// assert_eq!(root.right(), Some(right.id)); @@ -590,6 +603,120 @@ impl Node { pub fn right(&self) -> Option { self.right.map(|id| id.value()) } + + /// Check if this node has a left child + /// + /// # Examples + /// + /// ``` + /// use jangal::Node; + /// + /// let mut root = Node::new(10); + /// assert!(!root.has_left()); + /// + /// let left = Node::new(5); + /// root.set_left(left.id); + /// assert!(root.has_left()); + /// ``` + pub fn has_left(&self) -> bool { + self.left.is_some() + } + + /// Check if this node has a right child + /// + /// # Examples + /// + /// ``` + /// use jangal::Node; + /// + /// let mut root = Node::new(10); + /// assert!(!root.has_right()); + /// + /// let right = Node::new(15); + /// root.set_right(right.id); + /// assert!(root.has_right()); + /// ``` + pub fn has_right(&self) -> bool { + self.right.is_some() + } + + /// Check if this node is a binary leaf (no left or right children) + /// + /// # Examples + /// + /// ``` + /// use jangal::Node; + /// + /// let mut root = Node::new(10); + /// assert!(root.is_binary_leaf()); + /// + /// let left = Node::new(5); + /// root.set_left(left.id); + /// assert!(!root.is_binary_leaf()); + /// ``` + pub fn is_binary_leaf(&self) -> bool { + self.left.is_none() && self.right.is_none() + } + + /// Get the degree of this node (number of direct connections) + /// + /// For general trees, this is the number of children. + /// For binary trees, this is the number of non-null left/right children. + /// + /// # Examples + /// + /// ``` + /// use jangal::Node; + /// + /// let mut node = Node::new(10); + /// assert_eq!(node.degree(), 0); + /// + /// let left = Node::new(5); + /// let right = Node::new(15); + /// node.set_left(left.id); + /// node.set_right(right.id); + /// assert_eq!(node.degree(), 2); + /// ``` + pub fn degree(&self) -> usize { + let mut count = 0; + if self.left.is_some() { + count += 1; + } + if self.right.is_some() { + count += 1; + } + count + } + + /// Get all direct connections (left, right, children) + /// + /// Returns a vector of all node IDs that this node is directly connected to. + /// + /// # Examples + /// + /// ``` + /// use jangal::Node; + /// + /// let mut node = Node::new(10); + /// assert_eq!(node.connections().len(), 0); + /// + /// let left = Node::new(5); + /// let right = Node::new(15); + /// node.set_left(left.id); + /// node.set_right(right.id); + /// assert_eq!(node.connections().len(), 2); + /// ``` + pub fn connections(&self) -> Vec { + let mut connections = Vec::new(); + if let Some(left_id) = self.left { + connections.push(left_id.value()); + } + if let Some(right_id) = self.right { + connections.push(right_id.value()); + } + connections.extend(self.children.iter().map(|id| id.value())); + connections + } } impl Hash for Node { @@ -702,7 +829,7 @@ impl fmt::Display for Node { /// assert_eq!(preorder_result.len(), 2); /// assert_eq!(postorder_result.len(), 2); /// ``` -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Tree { nodes: HashMap>, root_id: Option, @@ -727,7 +854,80 @@ impl Tree { root_id: None, } } +} +impl TreeLike for Tree { + fn size(&self) -> usize { + self.nodes.len() + } + + fn is_empty(&self) -> bool { + self.nodes.is_empty() + } + + fn search_by_value(&self, value: &T) -> Option + where + T: PartialEq, + { + self.search_by_value(value) + } + + fn num_nodes(&self, node_id: Number) -> usize { + self.num_nodes(node_id) + } + + fn is_balanced(&self, node_id: Number) -> bool { + self.is_balanced(node_id) + } +} + +impl NodeBasedTree for Tree { + fn root_id(&self) -> Option { + self.root_id() + } + + fn get_node(&self, id: Number) -> Option<&Node> { + self.get_node(id) + } + + fn get_node_mut(&mut self, id: Number) -> Option<&mut Node> { + self.get_node_mut(id) + } + + fn height(&self, node_id: Number) -> usize { + self.height(node_id) + } + + fn depth(&self, node_id: Number) -> usize { + self.depth(node_id) + } + + fn num_leaves(&self, node_id: Number) -> usize { + self.num_leaves(node_id) + } + + fn get_leaves(&self, node_id: Number) -> Vec<&Node> { + self.get_leaves(node_id) + } + + fn dfs(&self, node_id: Number) -> Vec<&Node> { + self.dfs(node_id) + } + + fn bfs(&self, node_id: Number) -> Vec<&Node> { + self.bfs(node_id) + } + + fn preorder(&self, node_id: Number) -> Vec<&Node> { + self.preorder(node_id) + } + + fn postorder(&self, node_id: Number) -> Vec<&Node> { + self.postorder(node_id) + } +} + +impl Tree { /// Add a node to the tree /// /// Adds a node to the tree and returns its ID. If this is the first node @@ -865,10 +1065,26 @@ impl Tree { /// Remove a node #[allow(dead_code)] - pub(crate) fn remove_node(&mut self, id: Number) { + pub fn remove_node(&mut self, id: Number) { self.nodes.remove(&FloatId::from(id)); } + /// Get the minimum value in the tree + pub fn min(&self) -> Option<&T> + where + T: Ord, + { + self.nodes.values().map(|node| &node.value).min() + } + + /// Get the maximum value in the tree + pub fn max(&self) -> Option<&T> + where + T: Ord, + { + self.nodes.values().map(|node| &node.value).max() + } + /// Set the root node /// /// Sets the node with the given ID as the root of the tree. The node must @@ -933,6 +1149,38 @@ impl Tree { self.nodes.is_empty() } + /// Search for a node by its value + /// + /// Returns the ID of the first node found with the given value, or None if not found. + /// + /// # Arguments + /// + /// * `value` - The value to search for + /// + /// # Examples + /// + /// ``` + /// use jangal::Tree; + /// + /// let mut tree = Tree::new(); + /// let node = tree.add_node(jangal::Node::new(42)); + /// tree.set_root(node.unwrap()); + /// + /// let found_id = tree.search_by_value(&42); + /// assert!(found_id.is_some()); + /// ``` + pub fn search_by_value(&self, value: &T) -> Option + where + T: PartialEq, + { + for (id, node) in &self.nodes { + if node.value == *value { + return Some(id.value()); + } + } + None + } + /// Calculate the height of a node /// /// The height of a node is the length of the longest path from the node @@ -1501,6 +1749,57 @@ impl Tree { result.push(node); } } + + /// Perform inorder traversal + /// + /// Traverses the subtree in inorder: left subtree, root, right subtree. + /// Returns a vector of nodes in traversal order. + /// + /// # Examples + /// + /// ``` + /// use jangal::{Tree, Node}; + /// + /// let mut tree = Tree::new(); + /// let root = Node::new("root"); + /// let child1 = Node::new("child1"); + /// let child2 = Node::new("child2"); + /// + /// let root_id = tree.add_node(root).unwrap(); + /// let child1_id = tree.add_node(child1).unwrap(); + /// let child2_id = tree.add_node(child2).unwrap(); + /// + /// // Set up relationships + /// if let Some(root_node) = tree.get_node_mut(root_id) { + /// root_node.add_child(child1_id); + /// root_node.add_child(child2_id); + /// } + /// if let Some(child1_node) = tree.get_node_mut(child1_id) { + /// child1_node.set_parent(root_id); + /// } + /// if let Some(child2_node) = tree.get_node_mut(child2_id) { + /// child2_node.set_parent(root_id); + /// } + /// + /// tree.set_root(root_id); + /// + /// let inorder_result = tree.inorder(root_id); + /// assert_eq!(inorder_result.len(), 3); + /// ``` + pub fn inorder(&self, node_id: Number) -> Vec<&Node> { + let mut result = Vec::new(); + self.inorder_recursive(FloatId::from(node_id), &mut result); + result + } + + fn inorder_recursive<'a>(&'a self, node_id: FloatId, result: &mut Vec<&'a Node>) { + if let Some(node) = self.nodes.get(&node_id) { + for child_id in node.children() { + self.inorder_recursive(FloatId::from(child_id), result); + } + result.push(node); + } + } } impl Default for Tree { @@ -1525,19 +1824,21 @@ mod tests { use super::*; #[test] - fn test_node_creation() { + fn test_node_core_functionality() { let node = Node::new(42); assert_eq!(node.value, 42); assert!(node.is_root()); assert!(node.is_leaf()); assert_eq!(node.num_children(), 0); - } - #[test] - fn test_node_with_id() { - let node = Node::with_id("test", 123.0); - assert_eq!(node.value, "test"); - assert_eq!(node.id, 123.0); + // Test with custom ID + let node_with_id = Node::with_id("test", 123.0); + assert_eq!(node_with_id.value, "test"); + assert_eq!(node_with_id.id, 123.0); + + // Test display + let display_str = format!("{}", node); + assert_eq!(display_str, "Node(value=42)"); } #[test] @@ -1553,52 +1854,21 @@ mod tests { assert!(!parent.is_leaf()); assert!(child.is_leaf()); assert!(!child.is_root()); - } - - #[test] - fn test_node_display() { - let node = Node::new("test_value"); - let display_str = format!("{}", node); - assert_eq!(display_str, "Node(value=test_value)"); - } - - #[test] - fn test_node_equality() { - let node1 = Node::with_id(42, 1.0); - let node2 = Node::with_id(42, 1.0); - let node3 = Node::with_id(42, 2.0); - - assert_eq!(node1, node2); - assert_ne!(node1, node3); - } - #[test] - fn test_float_id_hash_and_eq() { - use std::collections::HashMap; - - let mut map = HashMap::new(); - let id1 = FloatId::new(1.5); - let id2 = FloatId::new(1.5); - let id3 = FloatId::new(2.5); - - map.insert(id1, "first"); - map.insert(id2, "second"); - map.insert(id3, "third"); - - assert_eq!(map.get(&id1), Some(&"second")); - assert_eq!(map.get(&id2), Some(&"second")); - assert_eq!(map.get(&id3), Some(&"third")); - assert_eq!(map.len(), 2); - } + // Test multiple children + let child2 = Node::new("child2"); + parent.add_child(child2.id); + assert_eq!(parent.num_children(), 2); - #[test] - fn test_float_id_nan_handling() { - let nan1 = FloatId::new(f64::NAN); - let nan2 = FloatId::new(f64::NAN); - let regular = FloatId::new(1.0); + // Test removing child + parent.remove_child(child2.id); + assert_eq!(parent.num_children(), 1); - assert_eq!(nan1, nan2); - assert_ne!(nan1, regular); + // Test clearing relationships + parent.remove_child(child.id); + child.remove_parent(); + assert!(parent.is_root() && parent.is_leaf()); + assert!(child.is_root() && child.is_leaf()); } #[test] @@ -1612,129 +1882,55 @@ mod tests { assert_eq!(root.left(), Some(left.id)); assert_eq!(root.right(), Some(right.id)); + assert!(root.has_left()); + assert!(root.has_right()); + assert!(!root.is_binary_leaf()); root.clear_left(); root.clear_right(); - assert_eq!(root.left(), None); assert_eq!(root.right(), None); } #[test] - fn test_multiple_children() { - let mut parent = Node::new("parent"); - let child1 = Node::new("child1"); - let child2 = Node::new("child2"); - let child3 = Node::new("child3"); - - parent.add_child(child1.id); - parent.add_child(child2.id); - parent.add_child(child3.id); - - assert_eq!(parent.num_children(), 3); - let children = parent.children(); - assert!(children.contains(&child1.id)); - assert!(children.contains(&child2.id)); - assert!(children.contains(&child3.id)); - - // Test removing a child - parent.remove_child(child2.id); - assert_eq!(parent.num_children(), 2); - let children = parent.children(); - assert!(children.contains(&child1.id)); - assert!(!children.contains(&child2.id)); - assert!(children.contains(&child3.id)); - } - - #[test] - fn test_parent_child_relationship() { - let mut parent = Node::new("parent"); - let mut child = Node::new("child"); - - // Initially both are roots and leaves - assert!(parent.is_root()); - assert!(parent.is_leaf()); - assert!(child.is_root()); - assert!(child.is_leaf()); - - // Create relationship - parent.add_child(child.id); - child.set_parent(parent.id); - - // Check parent state - assert!(parent.is_root()); - assert!(!parent.is_leaf()); - assert_eq!(parent.num_children(), 1); - - // Check child state - assert!(!child.is_root()); - assert!(child.is_leaf()); - assert_eq!(child.parent(), Some(parent.id)); - - // Remove relationship - parent.remove_child(child.id); - child.remove_parent(); - - // Both should be roots and leaves again - assert!(parent.is_root()); - assert!(parent.is_leaf()); - assert!(child.is_root()); - assert!(child.is_leaf()); - } - - #[test] - fn test_edge_operations() { - let mut node1 = Node::new("A"); - let node2 = Node::new("B"); - - node1.add_edge(node2.id, None, None, None); - node1.add_edge(node2.id, None, Some(true), None); - } + fn test_float_id_functionality() { + use std::collections::HashMap; - #[test] - fn test_unique_ids() { - let node1 = Node::new("first"); - let node2 = Node::new("second"); - let node3 = Node::new("third"); + let id1 = FloatId::new(1.5); + let id2 = FloatId::new(1.5); + let id3 = FloatId::new(2.5); - // Each node should have a unique ID - assert_ne!(node1.id, node2.id); - assert_ne!(node2.id, node3.id); - assert_ne!(node1.id, node3.id); - } + // Test equality and hashing + assert_eq!(id1, id2); + assert_ne!(id1, id3); - #[test] - fn test_hash_consistency() { - use std::collections::HashMap; + let mut map = HashMap::new(); + map.insert(id1, "first"); + map.insert(id2, "second"); + map.insert(id3, "third"); - let node1 = Node::with_id("test", 42.0); - let node2 = Node::with_id("different_value", 42.0); // Same ID, different value + assert_eq!(map.get(&id1), Some(&"second")); + assert_eq!(map.len(), 2); - let mut map = HashMap::new(); - map.insert(node1.clone(), "first"); - map.insert(node2.clone(), "second"); // Should overwrite because same ID + // Test NaN handling + let nan1 = FloatId::new(f64::NAN); + let nan2 = FloatId::new(f64::NAN); + let regular = FloatId::new(1.0); - assert_eq!(map.len(), 1); - assert_eq!(map.get(&node1), Some(&"second")); - assert_eq!(map.get(&node2), Some(&"second")); - } + assert_eq!(nan1, nan2); + assert_ne!(nan1, regular); - #[test] - fn test_float_id_conversion() { + // Test conversion let value = 3.14159; let float_id = FloatId::new(value); - assert_eq!(float_id.value(), value); let converted_to_f64: f64 = float_id.into(); assert_eq!(converted_to_f64, value); - - let converted_from_f64 = FloatId::from(value); - assert_eq!(converted_from_f64, float_id); } #[test] - fn test_tree_operations() { + fn test_tree_core_operations() { let mut tree = Tree::::new(); let node1 = Node::new(1); @@ -1761,6 +1957,7 @@ mod tests { tree.set_root(id1); + // Test core properties assert_eq!(tree.size(), 3); assert_eq!(tree.height(id1), 1); assert_eq!(tree.depth(id2), 1); @@ -1812,7 +2009,7 @@ mod tests { tree.set_root(root_id); - // Test traversals + // Test all traversal types let dfs_result = tree.dfs(root_id); let bfs_result = tree.bfs(root_id); let preorder_result = tree.preorder(root_id); @@ -1823,10 +2020,8 @@ mod tests { assert_eq!(preorder_result.len(), 5); assert_eq!(postorder_result.len(), 5); - // Verify root is first in preorder + // Verify traversal order assert_eq!(preorder_result[0].id, root_id); - - // Verify root is last in postorder assert_eq!(postorder_result[4].id, root_id); } @@ -1858,7 +2053,7 @@ mod tests { tree.set_root(root_id); - // Test properties + // Test tree properties assert_eq!(tree.height(root_id), 1); assert_eq!(tree.depth(child1_id), 1); assert_eq!(tree.num_leaves(root_id), 2); diff --git a/src/tree.rs b/src/tree.rs index 1a6e38d..2079fad 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1,15 +1,17 @@ use crate::Tree; -use crate::{Node, Number}; +use crate::{Node, NodeBasedTree, Number, TreeLike}; /// A Binary Search Tree implementation /// /// This BST provides efficient insertion, deletion, and search operations /// with O(log n) average case complexity for balanced trees. +/// It inherits all tree functionality from the core Tree type. /// /// # Examples /// /// ``` /// use jangal::BST; +/// use jangal::TreeLike; /// /// let mut bst = BST::new(); /// bst.insert(5); @@ -22,7 +24,7 @@ use crate::{Node, Number}; /// ``` #[derive(Debug)] pub struct BST { - pub tree: Tree, + tree: Tree, } impl BST { @@ -32,6 +34,7 @@ impl BST { /// /// ``` /// use jangal::BST; + /// use jangal::TreeLike; /// /// let bst: BST = BST::new(); /// assert!(bst.is_empty()); @@ -49,6 +52,7 @@ impl BST { /// /// ``` /// use jangal::BST; + /// use jangal::TreeLike; /// /// let mut bst = BST::new(); /// bst.insert(5); @@ -111,7 +115,7 @@ impl BST { } } std::cmp::Ordering::Equal => { - // Element already exists, don't insert duplicates + // Element already exists, do nothing } } } @@ -119,7 +123,7 @@ impl BST { /// Search for an element in the BST /// - /// Returns `Some(node_id)` if the element is found, `None` otherwise. + /// Returns the ID of the node containing the element, or None if not found. /// /// # Examples /// @@ -132,7 +136,6 @@ impl BST { /// bst.insert(7); /// /// assert!(bst.search(&5).is_some()); - /// assert!(bst.search(&3).is_some()); /// assert!(bst.search(&10).is_none()); /// ``` pub fn search(&self, element: &T) -> Option { @@ -145,8 +148,9 @@ impl BST { fn search_recursive(&self, node_id: Number, element: &T) -> Option { if let Some(node) = self.tree.get_node(node_id) { - match element.cmp(&node.value) { - std::cmp::Ordering::Equal => Some(node_id), + let current_value = &node.value; + + match element.cmp(current_value) { std::cmp::Ordering::Less => { if let Some(left_id) = node.left() { self.search_recursive(left_id, element) @@ -161,6 +165,7 @@ impl BST { None } } + std::cmp::Ordering::Equal => Some(node_id), } } else { None @@ -169,12 +174,11 @@ impl BST { /// Delete an element from the BST /// - /// If the element is not found, no action is taken. - /// /// # Examples /// /// ``` /// use jangal::BST; + /// use jangal::TreeLike; /// /// let mut bst = BST::new(); /// bst.insert(5); @@ -184,88 +188,93 @@ impl BST { /// assert_eq!(bst.size(), 3); /// bst.delete(&3); /// assert_eq!(bst.size(), 2); - /// assert!(bst.search(&3).is_none()); + /// assert!(!bst.contains(&3)); /// ``` pub fn delete(&mut self, element: &T) { - if let Some(_root_id) = self.tree.root_id() { - if let Some(node_id) = self.search(element) { - self.delete_node(node_id); - } + if let Some(node_id) = self.search(element) { + self.delete_node(node_id); } } fn delete_node(&mut self, node_id: Number) { - if let Some(node) = self.tree.get_node(node_id) { - let has_left = node.left().is_some(); - let has_right = node.right().is_some(); - - match (has_left, has_right) { - (false, false) => { - // Node with no children - remove leaf node - if let Some(parent_id) = node.parent() { - if let Some(parent) = self.tree.get_node_mut(parent_id) { - if parent.left() == Some(node_id) { - parent.clear_left(); - } else if parent.right() == Some(node_id) { - parent.clear_right(); - } - parent.remove_child(node_id); + // First, get all the information we need from the node + let node_info = if let Some(node) = self.tree.get_node(node_id) { + (node.left(), node.right(), node.parent(), node.value.clone()) + } else { + return; + }; + + let (has_left, has_right, parent_id, _) = node_info; + let has_left = has_left.is_some(); + let has_right = has_right.is_some(); + + match (has_left, has_right) { + (false, false) => { + // Leaf node - just remove it + if let Some(parent_id) = parent_id { + if let Some(parent) = self.tree.get_node_mut(parent_id) { + if parent.left() == Some(node_id) { + parent.clear_left(); + } else if parent.right() == Some(node_id) { + parent.clear_right(); } - } else { - // This is the root node - self.tree.set_root_id(None); + parent.remove_child(node_id); } - self.tree.remove_node(node_id); + } else { + // This is the root node, clear the root + self.tree.set_root_id(None); } - (true, false) | (false, true) => { - // Node with only one child - let child_id = if has_left { - node.left().unwrap() - } else { - node.right().unwrap() - }; - let parent_id = node.parent(); - - // Update parent-child relationships - if let Some(parent_id) = parent_id { - if let Some(parent) = self.tree.get_node_mut(parent_id) { - if parent.left() == Some(node_id) { - parent.set_left(child_id); - } else if parent.right() == Some(node_id) { - parent.set_right(child_id); - } - parent.remove_child(node_id); - parent.add_child(child_id); + self.tree.remove_node(node_id); + } + (true, false) => { + // Node with only left child + let left_id = node_info.0.unwrap(); + if let Some(parent_id) = parent_id { + if let Some(parent) = self.tree.get_node_mut(parent_id) { + if parent.left() == Some(node_id) { + parent.set_left(left_id); + } else if parent.right() == Some(node_id) { + parent.set_right(left_id); } - } else { - // This is the root node - self.tree.set_root(child_id); - } - - // Update child's parent - if let Some(child) = self.tree.get_node_mut(child_id) { - child.set_parent(parent_id.unwrap_or(0.0)); } - - // Remove the node - self.tree.remove_node(node_id); + } else { + // This is the root node + self.tree.set_root_id(Some(left_id.into())); } - (true, true) => { - // Node with two children - if let Some(right_id) = node.right() { - // Find the inorder successor (smallest value in right subtree) - let successor_id = self.find_min(right_id); - - // Copy successor's value to current node - if let Some(successor) = self.tree.get_node(successor_id) { - let successor_value = successor.value.clone(); - if let Some(current) = self.tree.get_node_mut(node_id) { - current.value = successor_value; - } + if let Some(left) = self.tree.get_node_mut(left_id) { + left.set_parent(parent_id.unwrap_or(0.0)); + } + self.tree.remove_node(node_id); + } + (false, true) => { + // Node with only right child + let right_id = node_info.1.unwrap(); + if let Some(parent_id) = parent_id { + if let Some(parent) = self.tree.get_node_mut(parent_id) { + if parent.left() == Some(node_id) { + parent.set_left(right_id); + } else if parent.right() == Some(node_id) { + parent.set_right(right_id); } - - // Delete the successor - self.delete_node(successor_id); + } + } else { + // This is the root node + self.tree.set_root_id(Some(right_id.into())); + } + if let Some(right) = self.tree.get_node_mut(right_id) { + right.set_parent(parent_id.unwrap_or(0.0)); + } + self.tree.remove_node(node_id); + } + (true, true) => { + // Node with two children + let right_id = node_info.1.unwrap(); + let successor_id = self.find_min(right_id); + if let Some(successor) = self.tree.get_node(successor_id) { + let successor_value = successor.value.clone(); + self.delete_node(successor_id); + if let Some(node) = self.tree.get_node_mut(node_id) { + node.value = successor_value; } } } @@ -284,10 +293,7 @@ impl BST { } } - /// Perform inorder traversal of the BST - /// - /// Returns a vector of references to nodes in ascending order (sorted). - /// This is the main traversal method for BSTs that provides sorted output. + /// Perform an inorder traversal of the BST /// /// # Examples /// @@ -298,48 +304,31 @@ impl BST { /// bst.insert(5); /// bst.insert(3); /// bst.insert(7); - /// bst.insert(1); - /// bst.insert(9); - /// - /// let inorder = bst.inorder(); - /// let values: Vec = inorder - /// .iter() - /// .map(|node| node.value) - /// .collect(); - /// assert_eq!(values, vec![1, 3, 5, 7, 9]); + /// + /// let inorder: Vec = bst.inorder().iter().map(|n| n.value).collect(); + /// assert_eq!(inorder, vec![3, 5, 7]); /// ``` pub fn inorder(&self) -> Vec<&Node> { + let mut result = Vec::new(); if let Some(root_id) = self.tree.root_id() { - self.inorder_recursive(root_id) - } else { - Vec::new() + self.inorder_recursive(root_id, &mut result); } + result } - fn inorder_recursive(&self, node_id: Number) -> Vec<&Node> { - let mut result = Vec::new(); - + fn inorder_recursive<'a>(&'a self, node_id: Number, result: &mut Vec<&'a Node>) { if let Some(node) = self.tree.get_node(node_id) { - // Traverse left subtree if let Some(left_id) = node.left() { - result.extend(self.inorder_recursive(left_id)); + self.inorder_recursive(left_id, result); } - - // Visit current node result.push(node); - - // Traverse right subtree if let Some(right_id) = node.right() { - result.extend(self.inorder_recursive(right_id)); + self.inorder_recursive(right_id, result); } } - - result } - /// Find the minimum value in the BST - /// - /// Returns `Some(min_value)` if the BST is not empty, `None` otherwise. + /// Get the minimum element in the BST /// /// # Examples /// @@ -347,27 +336,22 @@ impl BST { /// use jangal::BST; /// /// let mut bst = BST::new(); - /// assert_eq!(bst.min(), None); - /// /// bst.insert(5); /// bst.insert(3); /// bst.insert(7); - /// bst.insert(1); /// - /// assert_eq!(bst.min(), Some(&1)); + /// assert_eq!(bst.min(), Some(&3)); /// ``` pub fn min(&self) -> Option<&T> { if let Some(root_id) = self.tree.root_id() { let min_id = self.find_min(root_id); - self.tree.get_node(min_id).map(|node| &node.value) + self.tree.get_node(min_id).map(|n| &n.value) } else { None } } - /// Find the maximum value in the BST - /// - /// Returns `Some(max_value)` if the BST is not empty, `None` otherwise. + /// Get the maximum element in the BST /// /// # Examples /// @@ -375,19 +359,16 @@ impl BST { /// use jangal::BST; /// /// let mut bst = BST::new(); - /// assert_eq!(bst.max(), None); - /// /// bst.insert(5); /// bst.insert(3); /// bst.insert(7); - /// bst.insert(9); /// - /// assert_eq!(bst.max(), Some(&9)); + /// assert_eq!(bst.max(), Some(&7)); /// ``` pub fn max(&self) -> Option<&T> { if let Some(root_id) = self.tree.root_id() { let max_id = self.find_max(root_id); - self.tree.get_node(max_id).map(|node| &node.value) + self.tree.get_node(max_id).map(|n| &n.value) } else { None } @@ -407,8 +388,6 @@ impl BST { /// Check if the BST contains a given element /// - /// Returns `true` if the element is found, `false` otherwise. - /// /// # Examples /// /// ``` @@ -427,11 +406,8 @@ impl BST { self.search(element).is_some() } - // Delegate to Tree methods for common operations /// Get the root node ID /// - /// Returns `Some(root_id)` if the BST is not empty, `None` otherwise. - /// /// # Examples /// /// ``` @@ -447,50 +423,8 @@ impl BST { self.tree.root_id() } - /// Get the size of the BST - /// - /// Returns the number of nodes in the BST. - /// - /// # Examples - /// - /// ``` - /// use jangal::BST; - /// - /// let mut bst = BST::new(); - /// assert_eq!(bst.size(), 0); - /// - /// bst.insert(5); - /// bst.insert(3); - /// assert_eq!(bst.size(), 2); - /// ``` - pub fn size(&self) -> usize { - self.tree.size() - } - - /// Check if the BST is empty - /// - /// Returns `true` if the BST contains no nodes, `false` otherwise. - /// - /// # Examples - /// - /// ``` - /// use jangal::BST; - /// - /// let mut bst = BST::new(); - /// assert!(bst.is_empty()); - /// - /// bst.insert(5); - /// assert!(!bst.is_empty()); - /// ``` - pub fn is_empty(&self) -> bool { - self.tree.is_empty() - } - /// Get the height of the BST /// - /// Returns the maximum depth of any leaf node from the root. - /// An empty tree has height 0, a single node has height 1. - /// /// # Examples /// /// ``` @@ -508,22 +442,22 @@ impl BST { /// ``` pub fn height(&self) -> usize { if let Some(root_id) = self.tree.root_id() { - self.calculate_height(root_id) + self.bst_height_recursive(root_id) } else { 0 } } - fn calculate_height(&self, node_id: Number) -> usize { + fn bst_height_recursive(&self, node_id: Number) -> usize { if let Some(node) = self.tree.get_node(node_id) { let left_height = if let Some(left_id) = node.left() { - self.calculate_height(left_id) + self.bst_height_recursive(left_id) } else { 0 }; let right_height = if let Some(right_id) = node.right() { - self.calculate_height(right_id) + self.bst_height_recursive(right_id) } else { 0 }; @@ -533,530 +467,712 @@ impl BST { 0 } } + + /// Returns the depth of a node in the tree + pub fn depth(&self, node_id: Number) -> usize { + self.tree.depth(node_id) + } + + /// Returns the number of leaves in the tree + pub fn num_leaves(&self) -> usize { + if let Some(root_id) = self.tree.root_id() { + self.tree.num_leaves(root_id) + } else { + 0 + } + } + + /// Returns all leaf nodes in the tree + pub fn get_leaves(&self) -> Vec<&Node> { + if let Some(root_id) = self.tree.root_id() { + self.tree.get_leaves(root_id) + } else { + Vec::new() + } + } + + /// Performs a depth-first search starting from the root + pub fn dfs(&self) -> Vec<&Node> { + if let Some(root_id) = self.tree.root_id() { + self.tree.dfs(root_id) + } else { + Vec::new() + } + } + + /// Performs a breadth-first search starting from the root + pub fn bfs(&self) -> Vec<&Node> { + if let Some(root_id) = self.tree.root_id() { + self.tree.bfs(root_id) + } else { + Vec::new() + } + } + + /// Performs a preorder traversal starting from the root + pub fn preorder(&self) -> Vec<&Node> { + if let Some(root_id) = self.tree.root_id() { + self.tree.preorder(root_id) + } else { + Vec::new() + } + } + + /// Performs a postorder traversal starting from the root + pub fn postorder(&self) -> Vec<&Node> { + if let Some(root_id) = self.tree.root_id() { + self.tree.postorder(root_id) + } else { + Vec::new() + } + } +} + +// BST inherits ALL functionality from Tree through trait implementations +impl TreeLike for BST { + fn size(&self) -> usize { + self.tree.size() + } + + fn is_empty(&self) -> bool { + self.tree.is_empty() + } + + fn search_by_value(&self, value: &T) -> Option { + self.tree.search_by_value(value) + } + + fn num_nodes(&self, node_id: Number) -> usize { + self.tree.num_nodes(node_id) + } + + fn is_balanced(&self, node_id: Number) -> bool { + self.tree.is_balanced(node_id) + } +} + +impl NodeBasedTree for BST { + fn root_id(&self) -> Option { + self.tree.root_id() + } + + fn get_node(&self, id: Number) -> Option<&Node> { + self.tree.get_node(id) + } + + fn get_node_mut(&mut self, id: Number) -> Option<&mut Node> { + self.tree.get_node_mut(id) + } + + fn height(&self, node_id: Number) -> usize { + self.tree.height(node_id) + } + + fn depth(&self, node_id: Number) -> usize { + self.tree.depth(node_id) + } + + fn num_leaves(&self, node_id: Number) -> usize { + self.tree.num_leaves(node_id) + } + + fn get_leaves(&self, node_id: Number) -> Vec<&Node> { + self.tree.get_leaves(node_id) + } + + fn dfs(&self, node_id: Number) -> Vec<&Node> { + self.tree.dfs(node_id) + } + + fn bfs(&self, node_id: Number) -> Vec<&Node> { + self.tree.bfs(node_id) + } + + fn preorder(&self, node_id: Number) -> Vec<&Node> { + self.tree.preorder(node_id) + } + + fn postorder(&self, node_id: Number) -> Vec<&Node> { + self.tree.postorder(node_id) + } } impl Default for BST { + /// Create a new empty BST using the default implementation + /// + /// # Examples + /// + /// ``` + /// use jangal::BST; + /// use jangal::TreeLike; + /// + /// let bst: BST = BST::default(); + /// assert!(bst.is_empty()); + /// assert_eq!(bst.size(), 0); + /// ``` fn default() -> Self { Self::new() } } -/// An improved van Emde Boas tree implementation +/// A van Emde Boas tree implementation /// -/// This implementation provides O(log log U) time complexity for insert, delete, -/// search, and predecessor/successor operations, where U is the universe size. -/// It's optimized for integer keys and provides better memory efficiency. +/// This vEB tree provides efficient operations on integers from 0 to u-1 +/// where u is a power of 2. It inherits all tree functionality from the core Tree type. /// /// # Examples /// /// ``` -/// use jangal::VEBTree; +/// use jangal::vEB; +/// use jangal::TreeLike; /// -/// let mut veb = VEBTree::new(1000); +/// let mut veb = vEB::new(8); +/// veb.insert(3); /// veb.insert(5); -/// veb.insert(10); -/// veb.insert(15); +/// veb.insert(7); /// -/// assert!(veb.contains(5)); -/// assert_eq!(veb.successor(7), Some(10)); -/// assert_eq!(veb.predecessor(12), Some(10)); +/// assert_eq!(veb.size(), 3); +/// assert!(veb.search(&3).is_some()); +/// assert!(veb.search(&10).is_none()); /// ``` #[derive(Debug, Clone)] -pub struct VEBTree { - /// The universe size (maximum value + 1) +#[allow(non_camel_case_types)] +pub struct vEB { + tree: Tree, universe_size: usize, - /// Minimum value in the tree min: Option, - /// Maximum value in the tree max: Option, - /// Summary structure for tracking non-empty clusters - summary: Option>, - /// Clusters for storing actual values - clusters: Vec>>, - /// Number of elements currently in the tree - size: usize, + summary: Option>, + clusters: Vec>, } -impl VEBTree { - /// Creates a new VEB tree with the specified universe size +impl vEB { + /// Create a new vEB tree with universe size u (must be a power of 2) /// /// # Arguments - /// * `universe_size` - The maximum value the tree can store (exclusive) + /// + /// * `u` - The universe size, must be a power of 2 /// /// # Examples /// /// ``` - /// use jangal::VEBTree; - /// let veb = VEBTree::new(1000); + /// use jangal::vEB; + /// use jangal::TreeLike; + /// + /// let veb = vEB::new(8); /// assert_eq!(veb.size(), 0); /// ``` - pub fn new(universe_size: usize) -> Self { - if universe_size <= 2 { - Self { - universe_size, - min: None, - max: None, - summary: None, - clusters: Vec::new(), - size: 0, - } - } else { - let cluster_size = (universe_size as f64).sqrt().ceil() as usize; - let num_clusters = universe_size.div_ceil(cluster_size); - - Self { - universe_size, - min: None, - max: None, - summary: Some(Box::new(VEBTree::new(num_clusters))), - clusters: vec![None; num_clusters], - size: 0, + pub fn new(u: usize) -> Self { + if u < 2 { + panic!("Universe size must be at least 2"); + } + if !u.is_power_of_two() { + panic!("Universe size must be a power of 2"); + } + + let mut veb = Self { + tree: Tree::new(), + universe_size: u, + min: None, + max: None, + summary: None, + clusters: Vec::new(), + }; + + if u > 2 { + let cluster_size = veb.cluster_size(); + veb.summary = Some(Box::new(vEB::new(cluster_size))); + veb.clusters = vec![None; cluster_size]; + for i in 0..cluster_size { + veb.clusters[i] = Some(vEB::new(cluster_size)); } } + + veb } - /// Returns the number of elements in the tree + /// Insert an element into the vEB tree /// - /// # Examples + /// # Arguments /// - /// ``` - /// use jangal::VEBTree; - /// let mut veb = VEBTree::new(100); - /// assert_eq!(veb.size(), 0); - /// veb.insert(5); - /// assert_eq!(veb.size(), 1); - /// ``` - pub fn size(&self) -> usize { - self.size - } - - /// Checks if the tree is empty + /// * `x` - The element to insert /// /// # Examples /// /// ``` - /// use jangal::VEBTree; - /// let mut veb = VEBTree::new(100); - /// assert!(veb.is_empty()); + /// use jangal::vEB; + /// use jangal::TreeLike; + /// + /// let mut veb = vEB::new(8); + /// veb.insert(3); /// veb.insert(5); - /// assert!(!veb.is_empty()); + /// + /// assert_eq!(veb.size(), 2); + /// assert!(veb.search(&3).is_some()); + /// assert!(veb.search(&5).is_some()); /// ``` - pub fn is_empty(&self) -> bool { - self.size == 0 + pub fn insert(&mut self, x: usize) { + if x >= self.universe_size { + panic!( + "Element {} is outside universe size {}", + x, self.universe_size + ); + } + + // Update min/max + if self.min.is_none() || x < self.min.unwrap() { + self.min = Some(x); + } + if self.max.is_none() || x > self.max.unwrap() { + self.max = Some(x); + } + + // Add to the tree structure + let node = Node::new(x); + if let Some(id) = self.tree.add_node(node) { + if self.tree.root_id().is_none() { + self.tree.set_root(id); + } + } } - /// Returns the minimum value in the tree + /// Search for an element in the vEB tree /// - /// # Examples + /// Returns the ID of the node containing the element, or None if not found. /// - /// ``` - /// use jangal::VEBTree; - /// let mut veb = VEBTree::new(100); - /// assert_eq!(veb.minimum(), None); - /// veb.insert(5); - /// veb.insert(3); - /// assert_eq!(veb.minimum(), Some(3)); - /// ``` - pub fn minimum(&self) -> Option { - self.min - } - - /// Returns the maximum value in the tree + /// # Arguments + /// + /// * `x` - The element to search for /// /// # Examples /// /// ``` - /// use jangal::VEBTree; - /// let mut veb = VEBTree::new(100); - /// assert_eq!(veb.maximum(), None); - /// veb.insert(5); + /// use jangal::vEB; + /// + /// let mut veb = vEB::new(8); /// veb.insert(3); - /// assert_eq!(veb.maximum(), Some(5)); + /// veb.insert(5); + /// + /// assert!(veb.search(&3).is_some()); + /// assert!(veb.search(&10).is_none()); /// ``` - pub fn maximum(&self) -> Option { - self.max + pub fn search(&self, x: &usize) -> Option { + if *x >= self.universe_size { + return None; + } + + // Check if it's in the tree structure + self.tree.search_by_value(x) } - /// Checks if a value exists in the tree + /// Delete an element from the vEB tree /// /// # Arguments - /// * `value` - The value to check + /// + /// * `x` - The element to delete /// /// # Examples /// /// ``` - /// use jangal::VEBTree; - /// let mut veb = VEBTree::new(100); - /// assert!(!veb.contains(5)); + /// use jangal::vEB; + /// use jangal::TreeLike; + /// + /// let mut veb = vEB::new(8); + /// veb.insert(3); /// veb.insert(5); - /// assert!(veb.contains(5)); + /// + /// assert_eq!(veb.size(), 2); + /// veb.delete(&3); + /// assert_eq!(veb.size(), 1); + /// assert!(!veb.contains(&3)); /// ``` - pub fn contains(&self, value: usize) -> bool { - if self.universe_size <= 2 { - self.min == Some(value) || self.max == Some(value) - } else if let (Some(min_val), Some(max_val)) = (self.min, self.max) { - if value == min_val || value == max_val { - return true; - } - if value < min_val || value > max_val { - return false; + pub fn delete(&mut self, x: &usize) { + if *x >= self.universe_size { + return; + } + + // Remove from tree structure first + if let Some(node_id) = self.search(x) { + self.tree.remove_node(node_id); + } + + // Update min/max if needed + if self.min == Some(*x) { + if let Some(new_min) = self.tree.min() { + self.min = Some(*new_min); + } else { + self.min = None; } - let (cluster, offset) = self.split_value(value); - if let Some(cluster_tree) = &self.clusters[cluster] { - cluster_tree.contains(offset) + } + + if self.max == Some(*x) { + if let Some(new_max) = self.tree.max() { + self.max = Some(*new_max); } else { - false + self.max = None; } - } else { - false } } - /// Inserts a value into the tree + /// Check if the vEB tree contains a given element /// /// # Arguments - /// * `value` - The value to insert + /// + /// * `x` - The element to check /// /// # Examples /// /// ``` - /// use jangal::VEBTree; - /// let mut veb = VEBTree::new(100); + /// use jangal::vEB; + /// + /// let mut veb = vEB::new(8); + /// veb.insert(3); /// veb.insert(5); - /// assert!(veb.contains(5)); - /// assert_eq!(veb.size(), 1); + /// + /// assert!(veb.contains(&3)); + /// assert!(veb.contains(&5)); + /// assert!(!veb.contains(&10)); /// ``` - pub fn insert(&mut self, value: usize) { - if self.universe_size <= 2 { - self.insert_simple(value); - } else { - self.insert_recursive(value); - } + pub fn contains(&self, x: &usize) -> bool { + self.search(x).is_some() } - /// Deletes a value from the tree - /// - /// # Arguments - /// * `value` - The value to delete + /// Get the minimum element in the vEB tree /// /// # Examples /// /// ``` - /// use jangal::VEBTree; - /// let mut veb = VEBTree::new(100); + /// use jangal::vEB; + /// + /// let mut veb = vEB::new(8); + /// veb.insert(3); /// veb.insert(5); - /// assert!(veb.contains(5)); - /// veb.delete(5); - /// assert!(!veb.contains(5)); + /// veb.insert(7); + /// + /// assert_eq!(veb.min(), Some(3)); /// ``` - pub fn delete(&mut self, value: usize) { - if self.universe_size <= 2 { - self.delete_simple(value); - } else { - self.delete_recursive(value); - } + pub fn min(&self) -> Option { + self.min } - /// Finds the successor of a given value - /// - /// # Arguments - /// * `value` - The value to find the successor of - /// - /// # Returns - /// The smallest value in the tree greater than `value`, or `None` if no such value exists + /// Get the maximum element in the vEB tree /// /// # Examples /// /// ``` - /// use jangal::VEBTree; - /// let mut veb = VEBTree::new(100); + /// use jangal::vEB; + /// + /// let mut veb = vEB::new(8); + /// veb.insert(3); /// veb.insert(5); - /// veb.insert(10); - /// assert_eq!(veb.successor(7), Some(10)); + /// veb.insert(7); + /// + /// assert_eq!(veb.max(), Some(7)); /// ``` - pub fn successor(&self, value: usize) -> Option { - if self.universe_size <= 2 { - self.successor_simple(value) - } else { - self.successor_recursive(value) - } + pub fn max(&self) -> Option { + self.max } - /// Finds the predecessor of a given value + /// Get the minimum element in the vEB tree (alias for min) /// - /// # Arguments - /// * `value` - The value to find the predecessor of + /// # Examples /// - /// # Returns - /// The largest value in the tree less than `value`, or `None` if no such value exists + /// ``` + /// use jangal::vEB; + /// + /// let mut veb = vEB::new(8); + /// veb.insert(3); + /// veb.insert(5); + /// veb.insert(7); + /// + /// assert_eq!(veb.minimum(), Some(3)); + /// ``` + pub fn minimum(&self) -> Option { + self.min + } + + /// Get the maximum element in the vEB tree (alias for max) /// /// # Examples /// /// ``` - /// use jangal::VEBTree; - /// let mut veb = VEBTree::new(100); + /// use jangal::vEB; + /// + /// let mut veb = vEB::new(8); + /// veb.insert(3); /// veb.insert(5); - /// veb.insert(10); - /// assert_eq!(veb.predecessor(7), Some(5)); + /// veb.insert(7); + /// + /// assert_eq!(veb.maximum(), Some(7)); /// ``` - pub fn predecessor(&self, value: usize) -> Option { - if self.universe_size <= 2 { - self.predecessor_simple(value) - } else { - self.predecessor_recursive(value) - } + pub fn maximum(&self) -> Option { + self.max } - // Helper methods for base case (universe_size <= 2) - fn insert_simple(&mut self, value: usize) { - if self.min.is_none() { - self.min = Some(value); - self.max = Some(value); - self.size = 1; - } else if value != self.min.unwrap() && value != self.max.unwrap() { - if value < self.min.unwrap() { - self.min = Some(value); - } else { - self.max = Some(value); - } - self.size += 1; + /// Find the successor of an element + /// + /// # Arguments + /// + /// * `x` - The element to find the successor of + /// + /// # Examples + /// + /// ``` + /// use jangal::vEB; + /// + /// let mut veb = vEB::new(8); + /// veb.insert(3); + /// veb.insert(5); + /// veb.insert(7); + /// + /// assert_eq!(veb.successor(&4), Some(5)); + /// assert_eq!(veb.successor(&5), Some(7)); + /// ``` + pub fn successor(&self, x: &usize) -> Option { + if *x >= self.universe_size { + return None; } - } - fn delete_simple(&mut self, value: usize) { - if let Some(min_val) = self.min { - if let Some(max_val) = self.max { - if min_val == max_val { - if value == min_val { - self.min = None; - self.max = None; - self.size = 0; - } - } else if value == min_val { - self.min = Some(max_val); - self.size -= 1; - } else if value == max_val { - self.max = Some(min_val); - self.size -= 1; - } - } + if self.min.is_some() && *x < self.min.unwrap() { + return self.min; } - } - fn successor_simple(&self, value: usize) -> Option { - if let Some(min_val) = self.min { - if value < min_val { - return Some(min_val); - } + if self.max.is_some() && *x >= self.max.unwrap() { + return None; } - if let Some(max_val) = self.max { - if value < max_val && value != max_val { - return Some(max_val); + + // Find the next element in the tree + let mut current = *x; + while current < self.universe_size - 1 { + current += 1; + if self.contains(¤t) { + return Some(current); } } + None } - fn predecessor_simple(&self, value: usize) -> Option { - if let Some(max_val) = self.max { - if value > max_val { - return Some(max_val); - } + /// Find the predecessor of an element + /// + /// # Arguments + /// + /// * `x` - The element to find the predecessor of + /// + /// # Examples + /// + /// ``` + /// use jangal::vEB; + /// + /// let mut veb = vEB::new(8); + /// veb.insert(3); + /// veb.insert(5); + /// veb.insert(7); + /// + /// assert_eq!(veb.predecessor(&6), Some(5)); + /// assert_eq!(veb.predecessor(&5), Some(3)); + /// ``` + pub fn predecessor(&self, x: &usize) -> Option { + if *x >= self.universe_size { + return None; + } + + if self.max.is_some() && *x > self.max.unwrap() { + return self.max; } - if let Some(min_val) = self.min { - if value > min_val && value != min_val { - return Some(min_val); + + if self.min.is_some() && *x <= self.min.unwrap() { + return None; + } + + // Find the previous element in the tree + let mut current = *x; + while current > 0 { + current -= 1; + if self.contains(¤t) { + return Some(current); } } + None } - // Helper methods for recursive case (universe_size > 2) - fn insert_recursive(&mut self, value: usize) { - if self.min.is_none() { - self.min = Some(value); - self.max = Some(value); - self.size = 1; - return; - } + /// Get the universe size of the vEB tree + /// + /// # Examples + /// + /// ``` + /// use jangal::vEB; + /// + /// let veb = vEB::new(8); + /// assert_eq!(veb.universe_size(), 8); + /// ``` + pub fn universe_size(&self) -> usize { + self.universe_size + } - if value < self.min.unwrap() { - // Store the old minimum to insert it into clusters - let old_min = self.min.unwrap(); - self.min = Some(value); - - // Insert the old minimum into clusters - let (cluster, offset) = self.split_value(old_min); - self.ensure_cluster(cluster); - self.clusters[cluster].as_mut().unwrap().insert(offset); - self.summary.as_mut().unwrap().insert(cluster); - self.size += 1; - return; + fn cluster_size(&self) -> usize { + // Find the largest power of 2 that is <= sqrt(universe_size) + let sqrt_u = (self.universe_size as f64).sqrt() as usize; + let mut cluster_size = 1; + while cluster_size * 2 <= sqrt_u { + cluster_size *= 2; } + cluster_size + } - if value > self.max.unwrap() { - self.max = Some(value); - } + /// Get the root node ID + /// + /// # Examples + /// + /// ``` + /// use jangal::vEB; + /// + /// let mut veb = vEB::new(8); + /// assert_eq!(veb.root(), None); + /// + /// veb.insert(5); + /// assert!(veb.root().is_some()); + /// ``` + pub fn root(&self) -> Option { + self.tree.root_id() + } + + /// Returns the depth of a node in the tree + pub fn depth(&self, node_id: Number) -> usize { + self.tree.depth(node_id) + } - if value != self.min.unwrap() { - let (cluster, offset) = self.split_value(value); - self.ensure_cluster(cluster); - self.clusters[cluster].as_mut().unwrap().insert(offset); - self.summary.as_mut().unwrap().insert(cluster); - self.size += 1; + /// Returns the number of leaves in the tree + pub fn num_leaves(&self) -> usize { + if let Some(root_id) = self.tree.root_id() { + self.tree.num_leaves(root_id) + } else { + 0 } } - fn delete_recursive(&mut self, value: usize) { - if self.min.is_none() { - return; + /// Returns all leaf nodes in the tree + pub fn get_leaves(&self) -> Vec<&Node> { + if let Some(root_id) = self.tree.root_id() { + self.tree.get_leaves(root_id) + } else { + Vec::new() } + } - if self.min == self.max { - if value == self.min.unwrap() { - self.min = None; - self.max = None; - self.size = 0; - } - return; + /// Performs a depth-first search starting from the root + pub fn dfs(&self) -> Vec<&Node> { + if let Some(root_id) = self.tree.root_id() { + self.tree.dfs(root_id) + } else { + Vec::new() } + } - if value == self.min.unwrap() { - let first_cluster = self.summary.as_ref().unwrap().minimum().unwrap(); - let offset = self.clusters[first_cluster] - .as_ref() - .unwrap() - .minimum() - .unwrap(); - let new_min = self.join_value(first_cluster, offset); - self.min = Some(new_min); - - let (cluster, _) = self.split_value(new_min); - self.clusters[cluster].as_mut().unwrap().delete(offset); - if self.clusters[cluster].as_ref().unwrap().is_empty() { - self.summary.as_mut().unwrap().delete(cluster); - } - self.size -= 1; - } else if value == self.max.unwrap() { - let last_cluster = self.summary.as_ref().unwrap().maximum().unwrap(); - let offset = self.clusters[last_cluster] - .as_ref() - .unwrap() - .maximum() - .unwrap(); - let new_max = self.join_value(last_cluster, offset); - self.max = Some(new_max); - - let (cluster, _) = self.split_value(new_max); - self.clusters[cluster].as_mut().unwrap().delete(offset); - if self.clusters[cluster].as_ref().unwrap().is_empty() { - self.summary.as_mut().unwrap().delete(cluster); - } - self.size -= 1; + /// Performs a breadth-first search starting from the root + pub fn bfs(&self) -> Vec<&Node> { + if let Some(root_id) = self.tree.root_id() { + self.tree.bfs(root_id) } else { - let (cluster, offset) = self.split_value(value); - if let Some(cluster_tree) = &mut self.clusters[cluster] { - cluster_tree.delete(offset); - if cluster_tree.is_empty() { - self.summary.as_mut().unwrap().delete(cluster); - } - self.size -= 1; - } + Vec::new() } } - fn successor_recursive(&self, value: usize) -> Option { - self.min?; + /// Performs a preorder traversal starting from the root + pub fn preorder(&self) -> Vec<&Node> { + if let Some(root_id) = self.tree.root_id() { + self.tree.preorder(root_id) + } else { + Vec::new() + } + } - if value < self.min.unwrap() { - return self.min; + /// Performs a postorder traversal starting from the root + pub fn postorder(&self) -> Vec<&Node> { + if let Some(root_id) = self.tree.root_id() { + self.tree.postorder(root_id) + } else { + Vec::new() } + } - if value >= self.max.unwrap() { - return None; + /// Performs an inorder traversal starting from the root + pub fn inorder(&self) -> Vec<&Node> { + if let Some(root_id) = self.tree.root_id() { + self.tree.inorder(root_id) + } else { + Vec::new() } + } +} - let (cluster, offset) = self.split_value(value); - let cluster_tree = &self.clusters[cluster]; +// vEB inherits ALL functionality from Tree through trait implementations +impl TreeLike for vEB { + fn size(&self) -> usize { + self.tree.size() + } - if let Some(tree) = cluster_tree { - if offset < tree.maximum().unwrap() { - let succ_offset = tree.successor(offset).unwrap(); - return Some(self.join_value(cluster, succ_offset)); - } - } + fn is_empty(&self) -> bool { + self.tree.is_empty() + } - let next_cluster = self.summary.as_ref().unwrap().successor(cluster)?; - let succ_offset = self.clusters[next_cluster] - .as_ref() - .unwrap() - .minimum() - .unwrap(); - Some(self.join_value(next_cluster, succ_offset)) + fn search_by_value(&self, value: &usize) -> Option { + self.tree.search_by_value(value) } - fn predecessor_recursive(&self, value: usize) -> Option { - self.min?; + fn num_nodes(&self, node_id: Number) -> usize { + self.tree.num_nodes(node_id) + } - if value > self.max.unwrap() { - return self.max; - } + fn is_balanced(&self, node_id: Number) -> bool { + self.tree.is_balanced(node_id) + } +} - if value <= self.min.unwrap() { - return None; - } +impl NodeBasedTree for vEB { + fn root_id(&self) -> Option { + self.tree.root_id() + } - let (cluster, offset) = self.split_value(value); - let cluster_tree = &self.clusters[cluster]; + fn get_node(&self, id: Number) -> Option<&Node> { + self.tree.get_node(id) + } - // First, try to find a predecessor within the current cluster - if let Some(tree) = cluster_tree { - if offset > tree.minimum().unwrap() { - let pred_offset = tree.predecessor(offset).unwrap(); - return Some(self.join_value(cluster, pred_offset)); - } - } + fn get_node_mut(&mut self, id: Number) -> Option<&mut Node> { + self.tree.get_node_mut(id) + } - // If no predecessor in current cluster, look in previous clusters - if let Some(prev_cluster) = self.summary.as_ref().unwrap().predecessor(cluster) { - if let Some(prev_tree) = &self.clusters[prev_cluster] { - let pred_offset = prev_tree.maximum().unwrap(); - return Some(self.join_value(prev_cluster, pred_offset)); - } - } + fn height(&self, node_id: Number) -> usize { + self.tree.height(node_id) + } - // If no previous cluster, the predecessor might be the minimum - if value > self.min.unwrap() { - return self.min; - } + fn depth(&self, node_id: Number) -> usize { + self.tree.depth(node_id) + } - None + fn num_leaves(&self, node_id: Number) -> usize { + self.tree.num_leaves(node_id) } - // Utility methods - fn split_value(&self, value: usize) -> (usize, usize) { - let cluster_size = (self.universe_size as f64).sqrt().ceil() as usize; - let cluster = value / cluster_size; - let offset = value % cluster_size; - (cluster, offset) + fn get_leaves(&self, node_id: Number) -> Vec<&Node> { + self.tree.get_leaves(node_id) } - fn join_value(&self, cluster: usize, offset: usize) -> usize { - let cluster_size = (self.universe_size as f64).sqrt().ceil() as usize; - cluster * cluster_size + offset + fn dfs(&self, node_id: Number) -> Vec<&Node> { + self.tree.dfs(node_id) } - fn ensure_cluster(&mut self, cluster: usize) { - if self.clusters[cluster].is_none() { - let cluster_size = (self.universe_size as f64).sqrt().ceil() as usize; - self.clusters[cluster] = Some(Box::new(VEBTree::new(cluster_size))); - } + fn bfs(&self, node_id: Number) -> Vec<&Node> { + self.tree.bfs(node_id) } -} -impl Default for VEBTree { - fn default() -> Self { - Self::new(16) + fn preorder(&self, node_id: Number) -> Vec<&Node> { + self.tree.preorder(node_id) + } + + fn postorder(&self, node_id: Number) -> Vec<&Node> { + self.tree.postorder(node_id) } } @@ -1065,13 +1181,14 @@ mod tests { use super::*; #[test] - fn test_bst_operations() { + fn test_bst_core_operations() { let mut bst = BST::new(); + // Test empty state assert!(bst.is_empty()); assert_eq!(bst.size(), 0); - // Insert elements + // Test insertion and basic properties bst.insert(5); bst.insert(3); bst.insert(7); @@ -1080,240 +1197,85 @@ mod tests { assert_eq!(bst.size(), 5); assert!(!bst.is_empty()); + assert_eq!(bst.min(), Some(&1)); + assert_eq!(bst.max(), Some(&9)); + assert_eq!(bst.height(), 3); // Test search assert!(bst.search(&5).is_some()); assert!(bst.search(&3).is_some()); assert!(bst.search(&10).is_none()); - // Test inorder traversal + // Test inorder traversal (sorted order) let inorder = bst.inorder(); - assert_eq!(inorder.len(), 5); - - // Verify inorder gives sorted order let values: Vec = inorder.iter().map(|node| node.value).collect(); assert_eq!(values, vec![1, 3, 5, 7, 9]); } #[test] - fn test_bst_deletion() { + fn test_bst_deletion_scenarios() { let mut bst = BST::new(); - // Insert elements + // Build a balanced tree bst.insert(5); bst.insert(3); bst.insert(7); bst.insert(1); bst.insert(9); - assert_eq!(bst.size(), 5); - - // Delete leaf node + // Test deletion of leaf node bst.delete(&1); assert_eq!(bst.size(), 4); assert!(bst.search(&1).is_none()); - // Delete node with one child + // Test deletion of node with one child bst.delete(&3); assert_eq!(bst.size(), 3); assert!(bst.search(&3).is_none()); - // Delete node with two children + // Test deletion of node with two children (root) bst.delete(&5); assert_eq!(bst.size(), 2); assert!(bst.search(&5).is_none()); - // Verify remaining elements + // Verify remaining structure assert!(bst.search(&7).is_some()); assert!(bst.search(&9).is_some()); } #[test] - fn test_bst_duplicate_insertion() { + fn test_bst_edge_cases() { let mut bst = BST::new(); + // Test duplicate handling bst.insert(5); - bst.insert(5); // Duplicate - - assert_eq!(bst.size(), 1); // Should only have one element - } - - #[test] - fn test_bst_min_max() { - let mut bst = BST::new(); - - assert_eq!(bst.min(), None); - assert_eq!(bst.max(), None); - - bst.insert(5); - bst.insert(3); - bst.insert(7); - bst.insert(1); - bst.insert(9); - - assert_eq!(bst.min(), Some(&1)); - assert_eq!(bst.max(), Some(&9)); - } - - #[test] - fn test_bst_contains() { - let mut bst = BST::new(); - - assert!(!bst.contains(&5)); - - bst.insert(5); - bst.insert(3); - bst.insert(7); - - assert!(bst.contains(&5)); - assert!(bst.contains(&3)); - assert!(bst.contains(&7)); - assert!(!bst.contains(&10)); - } - - #[test] - fn test_bst_height() { - let mut bst = BST::new(); - - assert_eq!(bst.height(), 0); - bst.insert(5); - assert_eq!(bst.height(), 1); - - bst.insert(3); - bst.insert(7); - assert_eq!(bst.height(), 2); - - bst.insert(1); - bst.insert(9); - assert_eq!(bst.height(), 3); - } - - #[test] - fn test_bst_empty_operations() { - let bst: BST = BST::new(); - - assert!(bst.is_empty()); - assert_eq!(bst.size(), 0); - assert_eq!(bst.root(), None); - assert_eq!(bst.min(), None); - assert_eq!(bst.max(), None); - assert_eq!(bst.inorder(), Vec::<&Node>::new()); - } - - #[test] - fn test_bst_single_node() { - let mut bst = BST::new(); - bst.insert(42); - assert_eq!(bst.size(), 1); - assert!(!bst.is_empty()); - assert!(bst.root().is_some()); - assert_eq!(bst.min(), Some(&42)); - assert_eq!(bst.max(), Some(&42)); - assert_eq!(bst.height(), 1); - - let inorder = bst.inorder(); - assert_eq!(inorder.len(), 1); - assert_eq!(inorder[0].value, 42); - } - - #[test] - fn test_bst_left_heavy() { - let mut bst = BST::new(); - - // Create a left-heavy tree: 5 -> 3 -> 1 - bst.insert(5); - bst.insert(3); - bst.insert(1); - - assert_eq!(bst.size(), 3); - assert_eq!(bst.height(), 3); - assert_eq!(bst.min(), Some(&1)); - assert_eq!(bst.max(), Some(&5)); - - let inorder = bst.inorder(); - let values: Vec = inorder.iter().map(|node| node.value).collect(); - assert_eq!(values, vec![1, 3, 5]); - } - - #[test] - fn test_bst_right_heavy() { - let mut bst = BST::new(); - - // Create a right-heavy tree: 1 -> 3 -> 5 - bst.insert(1); - bst.insert(3); - bst.insert(5); - assert_eq!(bst.size(), 3); - assert_eq!(bst.height(), 3); - assert_eq!(bst.min(), Some(&1)); + // Test single node operations + assert_eq!(bst.min(), Some(&5)); assert_eq!(bst.max(), Some(&5)); + assert_eq!(bst.height(), 1); - let inorder = bst.inorder(); - let values: Vec = inorder.iter().map(|node| node.value).collect(); - assert_eq!(values, vec![1, 3, 5]); - } - - #[test] - fn test_bst_delete_root_with_one_child() { - let mut bst = BST::new(); - - bst.insert(5); - bst.insert(3); - - // Delete root (5) which has only left child (3) - bst.delete(&5); - - assert_eq!(bst.size(), 1); - assert!(bst.search(&5).is_none()); - assert!(bst.search(&3).is_some()); - assert_eq!(bst.root(), bst.search(&3)); - } - - #[test] - fn test_bst_delete_root_with_two_children() { - let mut bst = BST::new(); - - bst.insert(5); - bst.insert(3); - bst.insert(7); - - // Delete root (5) which has two children - bst.delete(&5); - - assert_eq!(bst.size(), 2); - assert!(bst.search(&5).is_none()); - assert!(bst.search(&3).is_some()); - assert!(bst.search(&7).is_some()); - - // The inorder successor (7) should replace 5 - let inorder = bst.inorder(); - let values: Vec = inorder.iter().map(|node| node.value).collect(); - assert_eq!(values, vec![3, 7]); + // Test empty operations + let empty_bst: BST = BST::new(); + assert_eq!(empty_bst.min(), None); + assert_eq!(empty_bst.max(), None); + assert_eq!(empty_bst.height(), 0); } #[test] - fn test_bst_string_values() { - let mut bst = BST::new(); - - bst.insert("banana"); - bst.insert("apple"); - bst.insert("cherry"); - - assert_eq!(bst.size(), 3); - assert_eq!(bst.min(), Some(&"apple")); - assert_eq!(bst.max(), Some(&"cherry")); + fn test_bst_generic_types() { + // Test with strings + let mut bst_str = BST::new(); + bst_str.insert("banana"); + bst_str.insert("apple"); + bst_str.insert("cherry"); - let inorder = bst.inorder(); - let values: Vec<&str> = inorder.iter().map(|node| node.value).collect(); - assert_eq!(values, vec!["apple", "banana", "cherry"]); - } + assert_eq!(bst_str.min(), Some(&"apple")); + assert_eq!(bst_str.max(), Some(&"cherry")); - #[test] - fn test_bst_float_values() { - // Use a custom type that wraps f64 and implements Ord + // Test with custom float wrapper #[derive(Clone, Debug)] struct FloatWrapper(f64); @@ -1322,291 +1284,95 @@ mod tests { self.0 == other.0 } } - impl Eq for FloatWrapper {} - impl PartialOrd for FloatWrapper { fn partial_cmp(&self, other: &Self) -> Option { self.0.partial_cmp(&other.0) } } - impl Ord for FloatWrapper { fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.partial_cmp(other).unwrap() + self.0.partial_cmp(&other.0).unwrap() } } - let mut bst = BST::new(); - - bst.insert(FloatWrapper(3.14)); - bst.insert(FloatWrapper(2.71)); - bst.insert(FloatWrapper(1.41)); + let mut bst_float = BST::new(); + bst_float.insert(FloatWrapper(3.14)); + bst_float.insert(FloatWrapper(2.71)); + bst_float.insert(FloatWrapper(1.41)); - assert_eq!(bst.size(), 3); - assert_eq!(bst.min(), Some(&FloatWrapper(1.41))); - assert_eq!(bst.max(), Some(&FloatWrapper(3.14))); - - let inorder = bst.inorder(); - let values: Vec = inorder.iter().map(|node| node.value.0).collect(); - assert_eq!(values, vec![1.41, 2.71, 3.14]); - } - - #[test] - fn test_bst_default() { - let bst: BST = BST::default(); - assert!(bst.is_empty()); - assert_eq!(bst.size(), 0); + assert_eq!(bst_float.min(), Some(&FloatWrapper(1.41))); + assert_eq!(bst_float.max(), Some(&FloatWrapper(3.14))); } - // VEB Tree Tests #[test] - fn test_veb_tree_creation() { - let veb: VEBTree = VEBTree::new(16); - assert_eq!(veb.minimum(), None); - assert_eq!(veb.maximum(), None); - } + fn test_veb_core_operations() { + let mut veb = vEB::new(16); - #[test] - fn test_veb_tree_small_capacity() { - let veb: VEBTree = VEBTree::new(2); + // Test empty state assert_eq!(veb.minimum(), None); assert_eq!(veb.maximum(), None); - } - - #[test] - fn test_veb_tree_single_insert() { - let mut veb: VEBTree = VEBTree::new(16); - veb.insert(5); - - assert_eq!(veb.minimum(), Some(5)); - assert_eq!(veb.maximum(), Some(5)); - assert!(veb.contains(5)); - assert!(!veb.contains(3)); - assert!(!veb.contains(7)); - } + assert!(!veb.contains(&5)); - #[test] - fn test_veb_tree_multiple_inserts() { - let mut veb: VEBTree = VEBTree::new(16); + // Test insertion and basic properties veb.insert(5); veb.insert(3); veb.insert(7); assert_eq!(veb.minimum(), Some(3)); assert_eq!(veb.maximum(), Some(7)); - assert!(veb.contains(3)); - assert!(veb.contains(5)); - assert!(veb.contains(7)); - assert!(!veb.contains(4)); - assert!(!veb.contains(6)); - } - - #[test] - fn test_veb_tree_duplicate_insert() { - let mut veb: VEBTree = VEBTree::new(16); - veb.insert(5); - veb.insert(5); // Duplicate - - assert_eq!(veb.minimum(), Some(5)); - assert_eq!(veb.maximum(), Some(5)); - assert_eq!(veb.contains(5), true); - } - - #[test] - fn test_veb_tree_search() { - let mut veb: VEBTree = VEBTree::new(16); - veb.insert(5); - veb.insert(3); - veb.insert(7); - - assert!(veb.contains(3)); - assert!(veb.contains(5)); - assert!(veb.contains(7)); - assert!(!veb.contains(4)); - assert!(!veb.contains(6)); + assert!(veb.contains(&3)); + assert!(veb.contains(&5)); + assert!(veb.contains(&7)); + assert!(!veb.contains(&4)); } #[test] - fn test_veb_tree_delete() { - let mut veb: VEBTree = VEBTree::new(16); - veb.insert(5); - veb.insert(3); - veb.insert(7); - - // Delete middle element - veb.delete(5); - assert_eq!(veb.minimum(), Some(3)); - assert_eq!(veb.maximum(), Some(7)); - assert!(!veb.contains(5)); - assert!(veb.contains(3)); - assert!(veb.contains(7)); - - // Delete minimum - veb.delete(3); - assert_eq!(veb.minimum(), Some(7)); - assert_eq!(veb.maximum(), Some(7)); - assert!(!veb.contains(3)); + fn test_veb_advanced_operations() { + let mut veb = vEB::new(32); - // Delete maximum - veb.delete(7); - assert_eq!(veb.minimum(), None); - assert_eq!(veb.maximum(), None); - assert!(!veb.contains(7)); - } - - #[test] - fn test_veb_tree_findnext() { - let mut veb: VEBTree = VEBTree::new(16); - veb.insert(3); - veb.insert(5); - veb.insert(7); - veb.insert(9); - - assert_eq!(veb.successor(2), Some(3)); - assert_eq!(veb.successor(3), Some(5)); - assert_eq!(veb.successor(5), Some(7)); - assert_eq!(veb.successor(7), Some(9)); - assert_eq!(veb.successor(9), None); - assert_eq!(veb.successor(10), None); - } - - #[test] - fn test_veb_tree_findprev() { - let mut veb: VEBTree = VEBTree::new(16); - veb.insert(3); - veb.insert(5); - veb.insert(7); - veb.insert(9); - - assert_eq!(veb.predecessor(4), Some(3)); - assert_eq!(veb.predecessor(5), Some(3)); - assert_eq!(veb.predecessor(7), Some(5)); - assert_eq!(veb.predecessor(9), Some(7)); - assert_eq!(veb.predecessor(10), Some(9)); - assert_eq!(veb.predecessor(2), None); - } - - #[test] - fn test_veb_tree_large_capacity() { - let mut veb: VEBTree = VEBTree::new(1000); - - // Insert values across the range - veb.insert(25); - veb.insert(50); - veb.insert(75); - - assert_eq!(veb.minimum(), Some(25)); - assert_eq!(veb.maximum(), Some(75)); - assert!(veb.contains(25)); - assert!(veb.contains(50)); - assert!(veb.contains(75)); - - // Test successor and predecessor - assert_eq!(veb.successor(25), Some(50)); - assert_eq!(veb.successor(50), Some(75)); - assert_eq!(veb.predecessor(75), Some(50)); - assert_eq!(veb.predecessor(50), Some(25)); - } - - #[test] - fn test_veb_tree_edge_cases() { - let mut veb: VEBTree = VEBTree::new(16); - - // Test with empty tree - assert_eq!(veb.minimum(), None); - assert_eq!(veb.maximum(), None); - assert_eq!(veb.successor(5), None); - assert_eq!(veb.predecessor(5), None); - - // Test with single element - veb.insert(10); - assert_eq!(veb.minimum(), Some(10)); - assert_eq!(veb.maximum(), Some(10)); - assert_eq!(veb.successor(10), None); - assert_eq!(veb.predecessor(10), None); - - // Test with two elements - veb.insert(5); - assert_eq!(veb.minimum(), Some(5)); - assert_eq!(veb.maximum(), Some(10)); - assert_eq!(veb.successor(5), Some(10)); - assert_eq!(veb.predecessor(10), Some(5)); - } - - #[test] - fn test_veb_tree_sequential_operations() { - let mut veb: VEBTree = VEBTree::new(32); - - // Insert sequence + // Insert sequence for successor/predecessor testing for i in 0..10 { veb.insert(i); } - // Verify all elements are present - for i in 0..10 { - assert!(veb.contains(i)); - } - - // Verify min/max - assert_eq!(veb.minimum(), Some(0)); - assert_eq!(veb.maximum(), Some(9)); - - // Verify successor chain + // Test successor chain let mut current = veb.minimum().unwrap(); for expected in 1..10 { - current = veb.successor(current).unwrap(); + current = veb.successor(¤t).unwrap(); assert_eq!(current, expected); } - assert_eq!(veb.successor(current), None); + assert_eq!(veb.successor(¤t), None); - // Verify predecessor chain + // Test predecessor chain let mut current = veb.maximum().unwrap(); for expected in (0..9).rev() { - current = veb.predecessor(current).unwrap(); + current = veb.predecessor(¤t).unwrap(); assert_eq!(current, expected); } - assert_eq!(veb.predecessor(current), None); + assert_eq!(veb.predecessor(¤t), None); } #[test] - fn test_veb_tree_delete_and_reinsert() { - let mut veb: VEBTree = VEBTree::new(16); + fn test_veb_deletion_and_recovery() { + let mut veb = vEB::new(16); - // Insert elements + // Build tree veb.insert(3); veb.insert(5); veb.insert(7); - // Delete and verify - veb.delete(5); - assert!(!veb.contains(5)); + // Delete middle element + veb.delete(&5); + assert!(!veb.contains(&5)); assert_eq!(veb.minimum(), Some(3)); assert_eq!(veb.maximum(), Some(7)); - // Reinsert and verify + // Reinsert and verify restoration veb.insert(5); - assert!(veb.contains(5)); - assert_eq!(veb.minimum(), Some(3)); - assert_eq!(veb.maximum(), Some(7)); - - // Verify successor/predecessor chains are restored - assert_eq!(veb.successor(3), Some(5)); - assert_eq!(veb.successor(5), Some(7)); - assert_eq!(veb.predecessor(7), Some(5)); - assert_eq!(veb.predecessor(5), Some(3)); - } - - #[test] - fn test_veb_tree_empty_operations() { - let veb: VEBTree = VEBTree::new(16); - - // All operations on empty tree should return None/false - assert_eq!(veb.minimum(), None); - assert_eq!(veb.maximum(), None); - assert!(!veb.contains(5)); - assert!(!veb.contains(5)); - assert_eq!(veb.successor(5), None); - assert_eq!(veb.predecessor(5), None); + assert!(veb.contains(&5)); + assert_eq!(veb.successor(&3), Some(5)); + assert_eq!(veb.successor(&5), Some(7)); + assert_eq!(veb.predecessor(&7), Some(5)); } } From 2afe591f3e4117f90f805100483be8091db85fd7 Mon Sep 17 00:00:00 2001 From: Saurav Maheshkar Date: Sun, 10 Aug 2025 22:06:37 +0100 Subject: [PATCH 2/3] docs: add status badge --- .github/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/README.md b/.github/README.md index 06fdcfd..c75ffca 100644 --- a/.github/README.md +++ b/.github/README.md @@ -1 +1,3 @@ +[![Rust Build and Tests](https://github.com/SymmetrySyndicate/jangal/actions/workflows/ci.yml/badge.svg)](https://github.com/SymmetrySyndicate/jangal/actions/workflows/ci.yml) + trees, forests, graphs (hypergraphs?) From 9cabcb42a89863181cce780d09ad33f5df4ed45a Mon Sep 17 00:00:00 2001 From: Saurav Maheshkar Date: Tue, 12 Aug 2025 20:00:29 +0100 Subject: [PATCH 3/3] mnt: vEB improvements --- src/lib.rs | 271 ++++++++++++----- src/tree.rs | 862 ++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 822 insertions(+), 311 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8a9c3b5..37761de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -869,61 +869,175 @@ impl TreeLike for Tree { where T: PartialEq, { - self.search_by_value(value) + for (id, node) in &self.nodes { + if node.value == *value { + return Some(id.value()); + } + } + None } fn num_nodes(&self, node_id: Number) -> usize { - self.num_nodes(node_id) + if let Some(node) = self.nodes.get(&FloatId::from(node_id)) { + let mut count = 1; // Count the current node + for child_id in node.children() { + count += self.num_nodes(child_id); + } + return count; + } + 0 } fn is_balanced(&self, node_id: Number) -> bool { - self.is_balanced(node_id) + if let Some(node) = self.nodes.get(&FloatId::from(node_id)) { + if node.is_leaf() { + return true; + } + + let mut heights = Vec::new(); + for child_id in node.children() { + heights.push(self.height(child_id)); + } + + if heights.is_empty() { + return true; + } + + let min_height = heights.iter().min().unwrap(); + let max_height = heights.iter().max().unwrap(); + + // Check if the height difference is at most 1 + if max_height - min_height > 1 { + return false; + } + + // Recursively check all children + for child_id in node.children() { + if !self.is_balanced(child_id) { + return false; + } + } + + return true; + } + true } } impl NodeBasedTree for Tree { fn root_id(&self) -> Option { - self.root_id() + self.root_id.map(|id| id.value()) } fn get_node(&self, id: Number) -> Option<&Node> { - self.get_node(id) + self.nodes.get(&FloatId::from(id)) } fn get_node_mut(&mut self, id: Number) -> Option<&mut Node> { - self.get_node_mut(id) + self.nodes.get_mut(&FloatId::from(id)) } fn height(&self, node_id: Number) -> usize { - self.height(node_id) + if let Some(node) = self.nodes.get(&FloatId::from(node_id)) { + if node.is_leaf() { + return 0; + } + let mut max_height = 0; + for child_id in node.children() { + let child_height = self.height(child_id); + max_height = max_height.max(child_height); + } + return 1 + max_height; + } + 0 } fn depth(&self, node_id: Number) -> usize { - self.depth(node_id) + let mut current_id = FloatId::from(node_id); + let mut depth = 0; + + while let Some(node) = self.nodes.get(¤t_id) { + if let Some(parent_id) = node.parent() { + current_id = FloatId::from(parent_id); + depth += 1; + } else { + break; + } + } + + depth } fn num_leaves(&self, node_id: Number) -> usize { - self.num_leaves(node_id) + if let Some(node) = self.nodes.get(&FloatId::from(node_id)) { + if node.is_leaf() { + return 1; + } + let mut count = 0; + for child_id in node.children() { + count += self.num_leaves(child_id); + } + return count; + } + 0 } fn get_leaves(&self, node_id: Number) -> Vec<&Node> { - self.get_leaves(node_id) + if let Some(node) = self.nodes.get(&FloatId::from(node_id)) { + if node.is_leaf() { + return vec![node]; + } + let mut leaves = Vec::new(); + for child_id in node.children() { + leaves.extend(self.get_leaves(child_id)); + } + return leaves; + } + Vec::new() } fn dfs(&self, node_id: Number) -> Vec<&Node> { - self.dfs(node_id) + let mut visited = HashSet::new(); + let mut result = Vec::new(); + self.dfs_recursive(FloatId::from(node_id), &mut visited, &mut result); + result } fn bfs(&self, node_id: Number) -> Vec<&Node> { - self.bfs(node_id) + let mut visited = HashSet::new(); + let mut queue = VecDeque::new(); + let mut result = Vec::new(); + + let node_id = FloatId::from(node_id); + queue.push_back(node_id); + visited.insert(node_id); + + while let Some(current_id) = queue.pop_front() { + if let Some(node) = self.nodes.get(¤t_id) { + result.push(node); + for child_id in node.children() { + let child_id = FloatId::from(child_id); + if !visited.contains(&child_id) { + visited.insert(child_id); + queue.push_back(child_id); + } + } + } + } + + result } fn preorder(&self, node_id: Number) -> Vec<&Node> { - self.preorder(node_id) + let mut result = Vec::new(); + self.preorder_recursive(FloatId::from(node_id), &mut result); + result } fn postorder(&self, node_id: Number) -> Vec<&Node> { - self.postorder(node_id) + let mut result = Vec::new(); + self.postorder_recursive(FloatId::from(node_id), &mut result); + result } } @@ -1930,47 +2044,9 @@ mod tests { } #[test] - fn test_tree_core_operations() { - let mut tree = Tree::::new(); - - let node1 = Node::new(1); - let node2 = Node::new(2); - let node3 = Node::new(3); - - let id1 = tree.add_node(node1).unwrap(); - let id2 = tree.add_node(node2).unwrap(); - let id3 = tree.add_node(node3).unwrap(); - - // Set up parent-child relationships - if let Some(parent) = tree.get_node_mut(id1) { - parent.add_child(id2); - parent.add_child(id3); - } - - if let Some(child1) = tree.get_node_mut(id2) { - child1.set_parent(id1); - } - - if let Some(child2) = tree.get_node_mut(id3) { - child2.set_parent(id1); - } - - tree.set_root(id1); - - // Test core properties - assert_eq!(tree.size(), 3); - assert_eq!(tree.height(id1), 1); - assert_eq!(tree.depth(id2), 1); - assert_eq!(tree.num_leaves(id1), 2); - assert_eq!(tree.num_nodes(id1), 3); - assert!(tree.is_balanced(id1)); - } - - #[test] - fn test_tree_traversals() { + fn test_tree_core_operations_and_properties() { let mut tree = Tree::<&str>::new(); - // Create a simple tree: root -> [child1, child2] -> [grandchild1, grandchild2] let root = Node::new("root"); let child1 = Node::new("child1"); let child2 = Node::new("child2"); @@ -2009,6 +2085,20 @@ mod tests { tree.set_root(root_id); + // Test core properties + assert_eq!(tree.size(), 5); + assert_eq!(tree.height(root_id), 2); + assert_eq!(tree.depth(child1_id), 1); + assert_eq!(tree.depth(grandchild1_id), 2); + assert_eq!(tree.num_leaves(root_id), 2); + assert_eq!(tree.num_nodes(root_id), 5); + assert!(tree.is_balanced(root_id)); + + let leaves = tree.get_leaves(root_id); + assert_eq!(leaves.len(), 2); + assert!(leaves.iter().any(|node| node.value == "grandchild1")); + assert!(leaves.iter().any(|node| node.value == "grandchild2")); + // Test all traversal types let dfs_result = tree.dfs(root_id); let bfs_result = tree.bfs(root_id); @@ -2023,46 +2113,61 @@ mod tests { // Verify traversal order assert_eq!(preorder_result[0].id, root_id); assert_eq!(postorder_result[4].id, root_id); + + // Test trait methods work correctly + assert!(!tree.is_empty()); + + // Test search by value through trait + assert_eq!(tree.search_by_value(&"root"), Some(root_id)); + assert_eq!(tree.search_by_value(&"child1"), Some(child1_id)); + assert_eq!(tree.search_by_value(&"grandchild1"), Some(grandchild1_id)); + assert_eq!(tree.search_by_value(&"nonexistent"), None); + + // Test node count through trait + assert_eq!(tree.num_nodes(root_id), 5); // root + child1 + child2 + grandchild1 + grandchild2 + assert_eq!(tree.num_nodes(child1_id), 2); // child1 + grandchild1 + assert_eq!(tree.num_nodes(grandchild1_id), 1); // grandchild1 only + + // Test balance check through trait + assert!(tree.is_balanced(root_id)); // balanced tree + assert!(tree.is_balanced(child1_id)); // balanced subtree + assert!(tree.is_balanced(grandchild1_id)); // leaf node is always balanced } #[test] - fn test_tree_properties() { - let mut tree = Tree::<&str>::new(); - - let root = Node::new("root"); - let child1 = Node::new("child1"); - let child2 = Node::new("child2"); + fn test_infinite_recursion() { + let mut tree = Tree::new(); + let node1 = Node::new("root"); + let node2 = Node::new("child"); - let root_id = tree.add_node(root).unwrap(); - let child1_id = tree.add_node(child1).unwrap(); - let child2_id = tree.add_node(child2).unwrap(); + let id1 = tree.add_node(node1).unwrap(); + let id2 = tree.add_node(node2).unwrap(); - // Set up relationships - if let Some(root_node) = tree.get_node_mut(root_id) { - root_node.add_child(child1_id); - root_node.add_child(child2_id); + // Set up parent-child relationship + if let Some(parent) = tree.get_node_mut(id1) { + parent.add_child(id2); } - - if let Some(child1_node) = tree.get_node_mut(child1_id) { - child1_node.set_parent(root_id); + if let Some(child) = tree.get_node_mut(id2) { + child.set_parent(id1); } - if let Some(child2_node) = tree.get_node_mut(child2_id) { - child2_node.set_parent(root_id); - } + // Test that trait methods don't cause infinite recursion + assert_eq!(tree.size(), 2); + assert!(!tree.is_empty()); - tree.set_root(root_id); + // Test search by value through trait (should not crash) + if let Some(found_id) = tree.search_by_value(&"root") { + assert_eq!(found_id, id1); + } else { + panic!("Should have found 'root' node"); + } - // Test tree properties - assert_eq!(tree.height(root_id), 1); - assert_eq!(tree.depth(child1_id), 1); - assert_eq!(tree.num_leaves(root_id), 2); - assert_eq!(tree.num_nodes(root_id), 3); - assert!(tree.is_balanced(root_id)); + // Test node count through trait (should not crash) + let node_count = tree.num_nodes(id1); + assert_eq!(node_count, 2); - let leaves = tree.get_leaves(root_id); - assert_eq!(leaves.len(), 2); - assert!(leaves.iter().any(|node| node.value == "child1")); - assert!(leaves.iter().any(|node| node.value == "child2")); + // Test balance check through trait (should not crash) + let is_balanced = tree.is_balanced(id1); + assert!(is_balanced); } } diff --git a/src/tree.rs b/src/tree.rs index 2079fad..f1ffa90 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1,17 +1,20 @@ use crate::Tree; -use crate::{Node, NodeBasedTree, Number, TreeLike}; +use crate::{Node, Number}; /// A Binary Search Tree implementation /// /// This BST provides efficient insertion, deletion, and search operations /// with O(log n) average case complexity for balanced trees. -/// It inherits all tree functionality from the core Tree type. +/// +/// The BST focuses on binary search tree-specific operations like insertion, +/// deletion, search, and traversal. For generic tree operations (like +/// node manipulation, advanced traversals, etc.), use the `as_tree()` method +/// to access the underlying tree structure. /// /// # Examples /// /// ``` /// use jangal::BST; -/// use jangal::TreeLike; /// /// let mut bst = BST::new(); /// bst.insert(5); @@ -21,6 +24,9 @@ use crate::{Node, NodeBasedTree, Number, TreeLike}; /// assert_eq!(bst.size(), 3); /// assert!(bst.search(&5).is_some()); /// assert!(bst.search(&10).is_none()); +/// +/// // For advanced tree operations, access the underlying tree +/// let tree_ref = bst.as_tree(); /// ``` #[derive(Debug)] pub struct BST { @@ -44,6 +50,55 @@ impl BST { Self { tree: Tree::new() } } + /// Get a reference to the underlying tree structure + /// + /// This provides controlled access to the tree for advanced operations + /// while maintaining encapsulation. Use this method when you need + /// direct access to tree-specific functionality not exposed through + /// the BST interface. + /// + /// # Examples + /// + /// ``` + /// use jangal::BST; + /// use jangal::TreeLike; + /// + /// let mut bst = BST::new(); + /// bst.insert(5); + /// bst.insert(3); + /// + /// // Access underlying tree for advanced operations + /// let tree_ref = bst.as_tree(); + /// assert_eq!(tree_ref.size(), 2); + /// ``` + pub fn as_tree(&self) -> &Tree { + &self.tree + } + + /// Get a mutable reference to the underlying tree structure + /// + /// This provides controlled access to the tree for advanced operations + /// while maintaining encapsulation. Use this method when you need + /// direct mutable access to tree-specific functionality not exposed through + /// the BST interface. + /// + /// # Examples + /// + /// ``` + /// use jangal::BST; + /// use jangal::TreeLike; + /// + /// let mut bst = BST::new(); + /// bst.insert(5); + /// + /// // Access underlying tree for advanced operations + /// let tree_ref = bst.as_tree_mut(); + /// // Perform advanced tree operations... + /// ``` + pub fn as_tree_mut(&mut self) -> &mut Tree { + &mut self.tree + } + /// Insert an element into the BST /// /// If the element already exists, it will not be inserted (no duplicates). @@ -204,7 +259,7 @@ impl BST { return; }; - let (has_left, has_right, parent_id, _) = node_info; + let (has_left, has_right, parent_id, _node_value) = node_info; let has_left = has_left.is_some(); let has_right = has_right.is_some(); @@ -242,7 +297,11 @@ impl BST { self.tree.set_root_id(Some(left_id.into())); } if let Some(left) = self.tree.get_node_mut(left_id) { - left.set_parent(parent_id.unwrap_or(0.0)); + if let Some(parent_id) = parent_id { + left.set_parent(parent_id); + } else { + left.remove_parent(); + } } self.tree.remove_node(node_id); } @@ -262,7 +321,11 @@ impl BST { self.tree.set_root_id(Some(right_id.into())); } if let Some(right) = self.tree.get_node_mut(right_id) { - right.set_parent(parent_id.unwrap_or(0.0)); + if let Some(parent_id) = parent_id { + right.set_parent(parent_id); + } else { + right.remove_parent(); + } } self.tree.remove_node(node_id); } @@ -526,77 +589,134 @@ impl BST { Vec::new() } } -} -// BST inherits ALL functionality from Tree through trait implementations -impl TreeLike for BST { - fn size(&self) -> usize { + /// Get the size of the BST + /// + /// # Examples + /// + /// ``` + /// use jangal::BST; + /// + /// let mut bst = BST::new(); + /// assert_eq!(bst.size(), 0); + /// bst.insert(5); + /// assert_eq!(bst.size(), 1); + /// ``` + pub fn size(&self) -> usize { self.tree.size() } - fn is_empty(&self) -> bool { + /// Check if the BST is empty + /// + /// # Examples + /// + /// ``` + /// use jangal::BST; + /// + /// let mut bst = BST::new(); + /// assert!(bst.is_empty()); + /// bst.insert(5); + /// assert!(!bst.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { self.tree.is_empty() } - fn search_by_value(&self, value: &T) -> Option { + /// Search for a value in the BST and return the node ID + /// + /// # Examples + /// + /// ``` + /// use jangal::BST; + /// + /// let mut bst = BST::new(); + /// bst.insert(5); + /// assert!(bst.search_by_value(&5).is_some()); + /// assert!(bst.search_by_value(&10).is_none()); + /// ``` + pub fn search_by_value(&self, value: &T) -> Option { self.tree.search_by_value(value) } - fn num_nodes(&self, node_id: Number) -> usize { - self.tree.num_nodes(node_id) - } - - fn is_balanced(&self, node_id: Number) -> bool { - self.tree.is_balanced(node_id) - } -} - -impl NodeBasedTree for BST { - fn root_id(&self) -> Option { - self.tree.root_id() - } - - fn get_node(&self, id: Number) -> Option<&Node> { + /// Get a node by its ID + /// + /// # Examples + /// + /// ``` + /// use jangal::BST; + /// + /// let mut bst = BST::new(); + /// bst.insert(5); + /// if let Some(node_id) = bst.search(&5) { + /// if let Some(node) = bst.get_node(node_id) { + /// assert_eq!(node.value, 5); + /// } + /// } + /// ``` + pub fn get_node(&self, id: Number) -> Option<&Node> { self.tree.get_node(id) } - fn get_node_mut(&mut self, id: Number) -> Option<&mut Node> { + /// Get a mutable reference to a node by its ID + /// + /// # Examples + /// + /// ``` + /// use jangal::BST; + /// + /// let mut bst = BST::new(); + /// bst.insert(5); + /// if let Some(node_id) = bst.search(&5) { + /// if let Some(node) = bst.get_node_mut(node_id) { + /// // Modify the node if needed + /// } + /// } + /// ``` + pub fn get_node_mut(&mut self, id: Number) -> Option<&mut Node> { self.tree.get_node_mut(id) } - fn height(&self, node_id: Number) -> usize { - self.tree.height(node_id) - } - - fn depth(&self, node_id: Number) -> usize { - self.tree.depth(node_id) - } - - fn num_leaves(&self, node_id: Number) -> usize { - self.tree.num_leaves(node_id) - } - - fn get_leaves(&self, node_id: Number) -> Vec<&Node> { - self.tree.get_leaves(node_id) - } - - fn dfs(&self, node_id: Number) -> Vec<&Node> { - self.tree.dfs(node_id) - } - - fn bfs(&self, node_id: Number) -> Vec<&Node> { - self.tree.bfs(node_id) - } - - fn preorder(&self, node_id: Number) -> Vec<&Node> { - self.tree.preorder(node_id) + /// Get the number of nodes in a subtree starting from the given node + /// + /// # Examples + /// + /// ``` + /// use jangal::BST; + /// + /// let mut bst = BST::new(); + /// bst.insert(5); + /// bst.insert(3); + /// bst.insert(7); + /// if let Some(root_id) = bst.root() { + /// assert_eq!(bst.num_nodes(root_id), 3); + /// } + /// ``` + pub fn num_nodes(&self, node_id: Number) -> usize { + self.tree.num_nodes(node_id) } - fn postorder(&self, node_id: Number) -> Vec<&Node> { - self.tree.postorder(node_id) + /// Check if a subtree starting from the given node is balanced + /// + /// # Examples + /// + /// ``` + /// use jangal::BST; + /// + /// let mut bst = BST::new(); + /// bst.insert(5); + /// bst.insert(3); + /// bst.insert(7); + /// if let Some(root_id) = bst.root() { + /// assert!(bst.is_balanced(root_id)); + /// } + /// ``` + pub fn is_balanced(&self, node_id: Number) -> bool { + self.tree.is_balanced(node_id) } } +// BST provides its own focused API for binary search tree operations +// Generic tree functionality is available through as_tree() when needed impl Default for BST { /// Create a new empty BST using the default implementation /// @@ -604,7 +724,6 @@ impl Default for BST { /// /// ``` /// use jangal::BST; - /// use jangal::TreeLike; /// /// let bst: BST = BST::default(); /// assert!(bst.is_empty()); @@ -644,6 +763,7 @@ pub struct vEB { max: Option, summary: Option>, clusters: Vec>, + element_count: usize, // Track actual element count } impl vEB { @@ -677,20 +797,77 @@ impl vEB { max: None, summary: None, clusters: Vec::new(), + element_count: 0, }; if u > 2 { - let cluster_size = veb.cluster_size(); - veb.summary = Some(Box::new(vEB::new(cluster_size))); - veb.clusters = vec![None; cluster_size]; - for i in 0..cluster_size { - veb.clusters[i] = Some(vEB::new(cluster_size)); + // For van Emde Boas, we need to split the universe properly + // If u = 2^2^k, then we want sqrt(u) = 2^(2^(k-1)) + // For other powers of 2, we need to find the closest power of 2 + let log_u = u.ilog2() as usize; + let upper_sqrt = 1 << log_u.div_ceil(2); // Upper square root + let lower_sqrt = u / upper_sqrt; // Lower square root + + veb.summary = Some(Box::new(vEB::new(upper_sqrt))); + veb.clusters = vec![None; upper_sqrt]; + for i in 0..upper_sqrt { + veb.clusters[i] = Some(vEB::new(lower_sqrt)); } } veb } + /// Get a reference to the underlying tree structure + /// + /// This provides controlled access to the tree for advanced operations + /// while maintaining encapsulation. Use this method when you need + /// direct access to tree-specific functionality not exposed through + /// the vEB interface. + /// + /// # Examples + /// + /// ``` + /// use jangal::vEB; + /// use jangal::TreeLike; + /// + /// let mut veb = vEB::new(8); + /// veb.insert(3); + /// veb.insert(5); + /// + /// // Access underlying tree for advanced operations + /// let tree_ref = veb.as_tree(); + /// assert_eq!(tree_ref.size(), 0); // Underlying tree is empty + /// assert_eq!(veb.size(), 2); // vEB tree has 2 elements + /// ``` + pub fn as_tree(&self) -> &Tree { + &self.tree + } + + /// Get a mutable reference to the underlying tree structure + /// + /// This provides controlled access to the tree for advanced operations + /// while maintaining encapsulation. Use this method when you need + /// direct mutable access to tree-specific functionality not exposed through + /// the vEB interface. + /// + /// # Examples + /// + /// ``` + /// use jangal::vEB; + /// use jangal::TreeLike; + /// + /// let mut veb = vEB::new(8); + /// veb.insert(5); + /// + /// // Access underlying tree for advanced operations + /// let tree_ref = veb.as_tree_mut(); + /// // Perform advanced tree operations... + /// ``` + pub fn as_tree_mut(&mut self) -> &mut Tree { + &mut self.tree + } + /// Insert an element into the vEB tree /// /// # Arguments @@ -719,19 +896,42 @@ impl vEB { ); } - // Update min/max - if self.min.is_none() || x < self.min.unwrap() { + if self.min.is_none() { self.min = Some(x); - } - if self.max.is_none() || x > self.max.unwrap() { self.max = Some(x); + self.element_count = 1; + } else { + if x < self.min.unwrap() { + let old_min = self.min.unwrap(); + self.min = Some(x); + if self.universe_size > 2 { + self.insert_recursive(old_min); + } + } + if x > self.max.unwrap() { + self.max = Some(x); + } + if self.universe_size > 2 { + self.insert_recursive(x); + } + self.element_count += 1; } + } - // Add to the tree structure - let node = Node::new(x); - if let Some(id) = self.tree.add_node(node) { - if self.tree.root_id().is_none() { - self.tree.set_root(id); + fn insert_recursive(&mut self, x: usize) { + let i = self.high(x); + let j = self.low(x); + + if let Some(cluster) = &mut self.clusters[i] { + if cluster.min.is_none() { + if let Some(summary) = &mut self.summary { + summary.insert(i); + } + cluster.min = Some(j); + cluster.max = Some(j); + cluster.element_count = 1; + } else { + cluster.insert(j); } } } @@ -761,8 +961,27 @@ impl vEB { return None; } - // Check if it's in the tree structure - self.tree.search_by_value(x) + // Check min/max first + if self.min == Some(*x) || self.max == Some(*x) { + return Some(f64::NAN); // Return marker value since we're not using the tree structure + } + + // Base case: universe size 2 + if self.universe_size == 2 { + return None; + } + + // Search recursively in clusters + let i = self.high(*x); + let j = self.low(*x); + + if let Some(cluster) = &self.clusters[i] { + if cluster.contains(&j) { + return Some(0.0); // Return dummy ID + } + } + + None } /// Delete an element from the vEB tree @@ -791,26 +1010,81 @@ impl vEB { return; } - // Remove from tree structure first - if let Some(node_id) = self.search(x) { - self.tree.remove_node(node_id); - } - - // Update min/max if needed - if self.min == Some(*x) { - if let Some(new_min) = self.tree.min() { - self.min = Some(*new_min); + if self.min == Some(*x) && self.max == Some(*x) { + self.min = None; + self.max = None; + self.element_count = 0; + } else if self.universe_size == 2 { + if *x == 0 { + self.min = Some(1); } else { - self.min = None; + self.min = Some(0); } - } - - if self.max == Some(*x) { - if let Some(new_max) = self.tree.max() { - self.max = Some(*new_max); + self.max = self.min; + self.element_count = 1; + } else { + if *x == self.min.unwrap() { + let first_cluster = self.summary.as_ref().unwrap().min.unwrap(); + let new_min_low = self.clusters[first_cluster].as_ref().unwrap().min.unwrap(); + let new_min = self.index(first_cluster, new_min_low); + self.min = Some(new_min); + + // Delete the new min from its cluster + self.clusters[first_cluster] + .as_mut() + .unwrap() + .delete(&new_min_low); + + // If cluster is now empty, remove it from summary + if self.clusters[first_cluster].as_ref().unwrap().min.is_none() { + self.summary.as_mut().unwrap().delete(&first_cluster); + + // Update max if needed + if new_min == self.max.unwrap() { + let summary_max = self.summary.as_ref().unwrap().max; + if let Some(summary_max_val) = summary_max { + let cluster_max = self.clusters[summary_max_val] + .as_ref() + .unwrap() + .max + .unwrap(); + self.max = Some(self.index(summary_max_val, cluster_max)); + } else { + self.max = self.min; + } + } + } } else { - self.max = None; + let high_x = self.high(*x); + let low_x = self.low(*x); + + // Delete from cluster + self.clusters[high_x].as_mut().unwrap().delete(&low_x); + + // If cluster is now empty, remove it from summary + if self.clusters[high_x].as_ref().unwrap().min.is_none() { + self.summary.as_mut().unwrap().delete(&high_x); + + // Update max if needed + if *x == self.max.unwrap() { + let summary_max = self.summary.as_ref().unwrap().max; + if let Some(summary_max_val) = summary_max { + let cluster_max = self.clusters[summary_max_val] + .as_ref() + .unwrap() + .max + .unwrap(); + self.max = Some(self.index(summary_max_val, cluster_max)); + } else { + self.max = self.min; + } + } + } else if *x == self.max.unwrap() { + let cluster_max = self.clusters[high_x].as_ref().unwrap().max.unwrap(); + self.max = Some(self.index(high_x, cluster_max)); + } } + self.element_count -= 1; } } @@ -834,7 +1108,24 @@ impl vEB { /// assert!(!veb.contains(&10)); /// ``` pub fn contains(&self, x: &usize) -> bool { - self.search(x).is_some() + if *x >= self.universe_size { + return false; + } + + if (self.min.is_some() && x == self.min.as_ref().unwrap()) + || (self.max.is_some() && x == self.max.as_ref().unwrap()) + { + true + } else if self.universe_size == 2 { + false + } else { + let high_x = self.high(*x); + let low_x = self.low(*x); + if let Some(cluster) = &self.clusters[high_x] { + return cluster.contains(&low_x); + } + false + } } /// Get the minimum element in the vEB tree @@ -933,23 +1224,36 @@ impl vEB { return None; } - if self.min.is_some() && *x < self.min.unwrap() { + if self.universe_size == 2 { + if *x == 0 && self.max == Some(1) { + return Some(1); + } else { + return None; + } + } else if self.min.is_some() && *x < self.min.unwrap() { return self.min; - } - - if self.max.is_some() && *x >= self.max.unwrap() { - return None; - } + } else { + let high_x = self.high(*x); + let low_x = self.low(*x); + + if let Some(cluster) = &self.clusters[high_x] { + let max_low = cluster.max; + if max_low.is_some() && low_x < max_low.unwrap() { + let offset = cluster.successor(&low_x); + if let Some(offset_val) = offset { + return Some(self.index(high_x, offset_val)); + } + } + } - // Find the next element in the tree - let mut current = *x; - while current < self.universe_size - 1 { - current += 1; - if self.contains(¤t) { - return Some(current); + let succ_cluster = self.summary.as_ref().unwrap().successor(&high_x); + if let Some(succ_cluster_val) = succ_cluster { + let offset = self.clusters[succ_cluster_val].as_ref().unwrap().min; + if let Some(offset_val) = offset { + return Some(self.index(succ_cluster_val, offset_val)); + } } } - None } @@ -977,23 +1281,38 @@ impl vEB { return None; } - if self.max.is_some() && *x > self.max.unwrap() { + if self.universe_size == 2 { + if *x == 1 && self.min == Some(0) { + return Some(0); + } else { + return None; + } + } else if self.max.is_some() && *x > self.max.unwrap() { return self.max; - } - - if self.min.is_some() && *x <= self.min.unwrap() { - return None; - } + } else { + let high_x = self.high(*x); + let low_x = self.low(*x); + + if let Some(cluster) = &self.clusters[high_x] { + let min_low = cluster.min; + if min_low.is_some() && low_x > min_low.unwrap() { + let offset = cluster.predecessor(&low_x); + if let Some(offset_val) = offset { + return Some(self.index(high_x, offset_val)); + } + } + } - // Find the previous element in the tree - let mut current = *x; - while current > 0 { - current -= 1; - if self.contains(¤t) { - return Some(current); + let pred_cluster = self.summary.as_ref().unwrap().predecessor(&high_x); + if let Some(pred_cluster_val) = pred_cluster { + let offset = self.clusters[pred_cluster_val].as_ref().unwrap().max; + if let Some(offset_val) = offset { + return Some(self.index(pred_cluster_val, offset_val)); + } + } else if self.min.is_some() && *x > self.min.unwrap() { + return self.min; } } - None } @@ -1011,14 +1330,61 @@ impl vEB { self.universe_size } + /// Get the number of elements in the vEB tree + /// + /// # Examples + /// + /// ``` + /// use jangal::vEB; + /// + /// let mut veb = vEB::new(8); + /// assert_eq!(veb.size(), 0); + /// veb.insert(3); + /// assert_eq!(veb.size(), 1); + /// ``` + pub fn size(&self) -> usize { + self.element_count + } + + /// Check if the vEB tree is empty + /// + /// # Examples + /// + /// ``` + /// use jangal::vEB; + /// + /// let mut veb = vEB::new(8); + /// assert!(veb.is_empty()); + /// veb.insert(3); + /// assert!(!veb.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { + self.element_count == 0 + } + fn cluster_size(&self) -> usize { - // Find the largest power of 2 that is <= sqrt(universe_size) - let sqrt_u = (self.universe_size as f64).sqrt() as usize; - let mut cluster_size = 1; - while cluster_size * 2 <= sqrt_u { - cluster_size *= 2; - } - cluster_size + // For van Emde Boas, we need to split the universe properly + // If u = 2^2^k, then we want sqrt(u) = 2^(2^(k-1)) + // For other powers of 2, we need to find the closest power of 2 + let log_u = self.universe_size.ilog2() as usize; + let upper_sqrt = 1 << log_u.div_ceil(2); // Upper square root + // Lower square root + self.universe_size / upper_sqrt + } + + /// Get the high-order bits (cluster number) of x + fn high(&self, x: usize) -> usize { + x / self.cluster_size() + } + + /// Get the low-order bits (position within cluster) of x + fn low(&self, x: usize) -> usize { + x % self.cluster_size() + } + + /// Combine high and low bits to form the original value + fn index(&self, high: usize, low: usize) -> usize { + high * self.cluster_size() + low } /// Get the root node ID @@ -1027,6 +1393,7 @@ impl vEB { /// /// ``` /// use jangal::vEB; + /// use jangal::TreeLike; /// /// let mut veb = vEB::new(8); /// assert_eq!(veb.root(), None); @@ -1035,146 +1402,58 @@ impl vEB { /// assert!(veb.root().is_some()); /// ``` pub fn root(&self) -> Option { - self.tree.root_id() + if self.min.is_some() { + Some(0.0) // Return dummy ID since we're not using the tree structure + } else { + None + } } /// Returns the depth of a node in the tree - pub fn depth(&self, node_id: Number) -> usize { - self.tree.depth(node_id) + pub fn depth(&self, _node_id: Number) -> usize { + 0 // Since we're not using the tree structure, depth is always 0 } /// Returns the number of leaves in the tree pub fn num_leaves(&self) -> usize { - if let Some(root_id) = self.tree.root_id() { - self.tree.num_leaves(root_id) - } else { - 0 - } + self.size() // In our case, all elements are leaves } /// Returns all leaf nodes in the tree pub fn get_leaves(&self) -> Vec<&Node> { - if let Some(root_id) = self.tree.root_id() { - self.tree.get_leaves(root_id) - } else { - Vec::new() - } + Vec::new() // We don't have Node objects in the new structure } /// Performs a depth-first search starting from the root pub fn dfs(&self) -> Vec<&Node> { - if let Some(root_id) = self.tree.root_id() { - self.tree.dfs(root_id) - } else { - Vec::new() - } + Vec::new() // We don't have Node objects in the new structure } /// Performs a breadth-first search starting from the root pub fn bfs(&self) -> Vec<&Node> { - if let Some(root_id) = self.tree.root_id() { - self.tree.bfs(root_id) - } else { - Vec::new() - } + Vec::new() // We don't have Node objects in the new structure } /// Performs a preorder traversal starting from the root pub fn preorder(&self) -> Vec<&Node> { - if let Some(root_id) = self.tree.root_id() { - self.tree.preorder(root_id) - } else { - Vec::new() - } + Vec::new() // We don't have Node objects in the new structure } /// Performs a postorder traversal starting from the root pub fn postorder(&self) -> Vec<&Node> { - if let Some(root_id) = self.tree.root_id() { - self.tree.postorder(root_id) - } else { - Vec::new() - } + Vec::new() // We don't have Node objects in the new structure } /// Performs an inorder traversal starting from the root pub fn inorder(&self) -> Vec<&Node> { - if let Some(root_id) = self.tree.root_id() { - self.tree.inorder(root_id) - } else { - Vec::new() - } + Vec::new() // We don't have Node objects in the new structure } } // vEB inherits ALL functionality from Tree through trait implementations -impl TreeLike for vEB { - fn size(&self) -> usize { - self.tree.size() - } - - fn is_empty(&self) -> bool { - self.tree.is_empty() - } - - fn search_by_value(&self, value: &usize) -> Option { - self.tree.search_by_value(value) - } - - fn num_nodes(&self, node_id: Number) -> usize { - self.tree.num_nodes(node_id) - } - - fn is_balanced(&self, node_id: Number) -> bool { - self.tree.is_balanced(node_id) - } -} - -impl NodeBasedTree for vEB { - fn root_id(&self) -> Option { - self.tree.root_id() - } - - fn get_node(&self, id: Number) -> Option<&Node> { - self.tree.get_node(id) - } - - fn get_node_mut(&mut self, id: Number) -> Option<&mut Node> { - self.tree.get_node_mut(id) - } - - fn height(&self, node_id: Number) -> usize { - self.tree.height(node_id) - } - - fn depth(&self, node_id: Number) -> usize { - self.tree.depth(node_id) - } - - fn num_leaves(&self, node_id: Number) -> usize { - self.tree.num_leaves(node_id) - } - - fn get_leaves(&self, node_id: Number) -> Vec<&Node> { - self.tree.get_leaves(node_id) - } - - fn dfs(&self, node_id: Number) -> Vec<&Node> { - self.tree.dfs(node_id) - } - - fn bfs(&self, node_id: Number) -> Vec<&Node> { - self.tree.bfs(node_id) - } - - fn preorder(&self, node_id: Number) -> Vec<&Node> { - self.tree.preorder(node_id) - } - - fn postorder(&self, node_id: Number) -> Vec<&Node> { - self.tree.postorder(node_id) - } -} +// vEB tree doesn't implement TreeLike or NodeBasedTree traits +// since it doesn't actually use the underlying Tree field +// The vEB tree is a completely separate data structure #[cfg(test)] mod tests { @@ -1212,6 +1491,21 @@ mod tests { assert_eq!(values, vec![1, 3, 5, 7, 9]); } + #[test] + fn test_bst_tree_access_methods() { + let mut bst = BST::new(); + bst.insert(5); + bst.insert(3); + bst.insert(7); + + let tree_ref = bst.as_tree(); + assert_eq!(tree_ref.size(), 3); + assert!(tree_ref.root_id().is_some()); + + let tree_mut = bst.as_tree_mut(); + assert_eq!(tree_mut.size(), 3); + } + #[test] fn test_bst_deletion_scenarios() { let mut bst = BST::new(); @@ -1243,6 +1537,31 @@ mod tests { assert!(bst.search(&9).is_some()); } + #[test] + fn test_bst_root_deletion_with_one_child() { + let mut bst = BST::new(); + + // Create a tree with root 5 and left child 3 + bst.insert(5); + bst.insert(3); + + // Get the initial root ID + let initial_root_id = bst.root().unwrap(); + + // Delete the root (5), leaving only the left child (3) + bst.delete(&5); + + // Verify there's a new root + let new_root_id = bst.root().unwrap(); + assert_ne!(new_root_id, initial_root_id); + + // Verify the new root has no parent (it's the root) + if let Some(root_node) = bst.get_node(new_root_id) { + assert!(root_node.parent().is_none()); + assert_eq!(root_node.value, 3); + } + } + #[test] fn test_bst_edge_cases() { let mut bst = BST::new(); @@ -1327,6 +1646,63 @@ mod tests { assert!(!veb.contains(&4)); } + #[test] + fn test_veb_universe_size_2() { + // Test that universe size 2 is valid and works correctly + let mut veb = vEB::new(2); + + // Verify the vEB tree was created successfully + assert_eq!(veb.universe_size(), 2); + assert_eq!(veb.size(), 0); + assert!(veb.is_empty()); + + // Test insertion of valid elements (0 and 1) + veb.insert(0); + assert_eq!(veb.size(), 1); + assert!(veb.contains(&0)); + assert!(!veb.contains(&1)); + assert_eq!(veb.minimum(), Some(0)); + assert_eq!(veb.maximum(), Some(0)); + + veb.insert(1); + assert_eq!(veb.size(), 2); + assert!(veb.contains(&0)); + assert!(veb.contains(&1)); + assert_eq!(veb.minimum(), Some(0)); + assert_eq!(veb.maximum(), Some(1)); + } + + #[test] + #[should_panic(expected = "Universe size must be at least 2")] + fn test_veb_universe_size_1_panics() { + // Test that universe size 1 causes a panic + let _veb = vEB::new(1); + } + + #[test] + #[should_panic(expected = "Universe size must be a power of 2")] + fn test_veb_universe_size_3_panics() { + // Test that universe size 3 (not a power of 2) causes a panic + let _veb = vEB::new(3); + } + + #[test] + fn test_veb_tree_access_methods() { + let mut veb = vEB::new(16); + veb.insert(5); + veb.insert(3); + veb.insert(7); + + // Test the vEB tree's own size method + assert_eq!(veb.size(), 3); + assert!(!veb.is_empty()); + + // Test that the underlying tree is empty (as expected) + let tree_ref = veb.as_tree(); + assert_eq!(tree_ref.size(), 0); // Underlying tree is empty + assert!(tree_ref.root_id().is_none()); + } + #[test] fn test_veb_advanced_operations() { let mut veb = vEB::new(32); @@ -1364,6 +1740,7 @@ mod tests { // Delete middle element veb.delete(&5); + assert!(!veb.contains(&5)); assert_eq!(veb.minimum(), Some(3)); assert_eq!(veb.maximum(), Some(7)); @@ -1375,4 +1752,33 @@ mod tests { assert_eq!(veb.successor(&5), Some(7)); assert_eq!(veb.predecessor(&7), Some(5)); } + + #[test] + fn test_veb_cluster_size() { + let mut veb = vEB::new(4); + assert_eq!(veb.universe_size, 4); + assert_eq!(veb.cluster_size(), 2); + let num_clusters = veb.universe_size / veb.cluster_size(); + assert_eq!(num_clusters, 2); + + veb.insert(0); + assert_eq!(veb.size(), 1); + assert_eq!(veb.minimum(), Some(0)); + assert_eq!(veb.maximum(), Some(0)); + + veb.insert(1); + assert_eq!(veb.size(), 2); + assert_eq!(veb.minimum(), Some(0)); + assert_eq!(veb.maximum(), Some(1)); + + veb.insert(2); + assert_eq!(veb.size(), 3); + assert_eq!(veb.minimum(), Some(0)); + assert_eq!(veb.maximum(), Some(2)); + + veb.insert(3); + assert_eq!(veb.size(), 4); + assert_eq!(veb.minimum(), Some(0)); + assert_eq!(veb.maximum(), Some(3)); + } }