From fb556d6d8c70d31fdab2e2cceae112b4ed8ebaec Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Sat, 9 Aug 2025 21:58:27 -0300 Subject: [PATCH 1/3] feat: add traverse_mut method --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- src/lib.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 56e6c06..5b74bfc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "crossbeam-deque" @@ -29,7 +29,7 @@ checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "easy-tree" -version = "0.1.2" +version = "0.2.0" dependencies = [ "rayon", ] diff --git a/Cargo.toml b/Cargo.toml index bcb936f..d0f59e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "easy-tree" -version = "0.1.2" +version = "0.2.0" authors = ["Anton Suprunchuk "] edition = "2021" description = "A simple and efficient tree structure library for Rust with recursive traversal" diff --git a/src/lib.rs b/src/lib.rs index 426ce31..7224571 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -127,6 +127,8 @@ impl Node { /// A tree structure containing nodes. pub struct Tree { nodes: Vec>, + /// Stack for traverse_mut to avoid allocations + stack: Vec<(usize, bool)>, } impl Default for Tree { @@ -138,7 +140,10 @@ impl Default for Tree { impl Tree { /// Creates a new empty tree. pub fn new() -> Self { - Self { nodes: Vec::new() } + Self { + nodes: Vec::new(), + stack: Vec::new(), + } } /// Adds a new node with the given data to the tree and returns its index. The nodes @@ -236,6 +241,42 @@ impl Tree { } } + /// Walks the tree recursively, applying the given functions before and after processing the + /// children of each node. This version allows for mutable access to the nodes. + pub fn traverse_mut( + &mut self, + mut before_processing_children: impl FnMut(usize, &mut T, &mut S), + mut after_processing_the_subtree: impl FnMut(usize, &mut T, &mut S), + s: &mut S, + ) { + if self.is_empty() { + return; + } + + self.stack.clear(); + self.stack.push((0, false)); + + while let Some((index, children_visited)) = self.stack.pop() { + if children_visited { + // All children are processed, call f2 + let node = &mut self.nodes[index]; + after_processing_the_subtree(index, &mut node.data, s); + } else { + // Call f and mark this node's children for processing + let node = &mut self.nodes[index]; + before_processing_children(index, &mut node.data, s); + + // Re-push the current node with children_visited set to true + self.stack.push((index, true)); + + // Push all children onto the stack + for &child in node.children.iter().rev() { + self.stack.push((child, false)); + } + } + } + } + /// Returns an iterator over the indices and data of the nodes in the tree. pub fn iter(&self) -> impl Iterator { self.nodes @@ -360,12 +401,11 @@ mod tests { tree.traverse( |index, node, result| { - result.push(format!("Calling handler for node {}: {}", index, node)) + result.push(format!("Calling handler for node {index}: {node}")) }, |index, _node, result| { result.push(format!( - "Finished handling node {} and all it's children", - index + "Finished handling node {index} and all it's children" )) }, &mut result, From 1023c107c20e249a3466c536146deb4cee3d078c Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Sat, 9 Aug 2025 22:03:31 -0300 Subject: [PATCH 2/3] reformat --- src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e1eec58..a2ddd7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -687,12 +687,10 @@ mod tests { let mut result = vec![]; tree.traverse( - |index, node, result| { - result.push(format!("Calling handler for node {index}: {node}")) - }, + |index, node, result| result.push(format!("Calling handler for node {index}: {node}")), |index, _node, result| { result.push(format!( - "Finished handling node {index} and all it's children" + "Finished handling node {index} and all its children" )) }, &mut result, From fb97ff2973da613a1f206daa2ee7f624e889cf91 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Sat, 9 Aug 2025 22:07:04 -0300 Subject: [PATCH 3/3] fix grammar --- src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a2ddd7c..eb12386 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -702,11 +702,11 @@ mod tests { "Calling handler for node 0: 0", "Calling handler for node 1: 1", "Calling handler for node 3: 3", - "Finished handling node 3 and all it's children", - "Finished handling node 1 and all it's children", + "Finished handling node 3 and all its children", + "Finished handling node 1 and all its children", "Calling handler for node 2: 2", - "Finished handling node 2 and all it's children", - "Finished handling node 0 and all it's children", + "Finished handling node 2 and all its children", + "Finished handling node 0 and all its children", ] ); }