radiate_gp/collections/trees/
iter.rs

1use crate::collections::{Tree, TreeNode};
2use std::collections::VecDeque;
3
4/// Tree traversal iterators for pre-order, post-order, and breadth-first search.
5/// These iterators allow for efficient traversal of tree structures, providing
6/// a way to visit each node in the tree in different orders.
7///
8/// # PreOrderIterator
9/// The `PreOrderIterator` visits nodes in pre-order, meaning it visits the root
10/// node first, then recursively visits each child node from left to right.
11///
12/// # PostOrderIterator
13/// The `PostOrderIterator` visits nodes in post-order, meaning it recursively
14/// visits each child node from left to right, and then visits the root node.
15///
16/// # TreeBreadthFirstIterator
17/// The `TreeBreadthFirstIterator` visits nodes in breadth-first order, meaning
18/// it visits all nodes at the current depth before moving on to the next depth.
19///
20/// # Usage
21/// To use these iterators, you can call the `iter_pre_order`, `iter_post_order`,
22/// or `iter_breadth_first` methods on a `TreeNode` or `Tree` instance. These
23/// methods return an iterator that can be used to traverse the tree in the
24/// desired order.
25///
26/// # Example
27/// ```rust
28/// use radiate_gp::*;
29///
30/// // create a simple tree
31/// let tree = Tree::new(TreeNode::new(1)
32///     .attach(TreeNode::new(2)
33///         .attach(TreeNode::new(4))
34///         .attach(TreeNode::new(5)))
35///     .attach(TreeNode::new(3)
36///         .attach(TreeNode::new(6))
37///        .attach(TreeNode::new(7))));
38///
39/// // iterate over the tree in pre-order
40/// // Output: 1, 2, 4, 5, 3, 6, 7
41/// let pre_order = tree.iter_pre_order().map(|n| n.value()).collect::<Vec<&i32>>();
42///
43/// // iterate over the tree in post-order
44/// // Output: 4, 5, 2, 6, 7, 3, 1
45/// let post_order = tree.iter_post_order().map(|n| n.value()).collect::<Vec<&i32>>();
46///
47/// // iterate over the tree in breadth-first order
48/// // Output: 1, 2, 3, 4, 5, 6, 7
49/// let breadth_first = tree.iter_breadth_first().map(|n| n.value()).collect::<Vec<&i32>>();
50/// ```
51///
52pub trait TreeIterator<T> {
53    fn iter_pre_order(&self) -> PreOrderIterator<T>;
54    fn iter_post_order(&self) -> PostOrderIterator<T>;
55    fn iter_breadth_first(&self) -> TreeBreadthFirstIterator<T>;
56}
57
58/// Implement the `TreeIterator` trait for `TreeNode`
59///
60/// This allows for traversal of a single node and its children in pre-order, post-order, and breadth-first order.
61impl<T> TreeIterator<T> for TreeNode<T> {
62    fn iter_pre_order(&self) -> PreOrderIterator<T> {
63        PreOrderIterator { stack: vec![self] }
64    }
65
66    fn iter_post_order(&self) -> PostOrderIterator<T> {
67        PostOrderIterator {
68            stack: vec![(self, false)],
69        }
70    }
71
72    fn iter_breadth_first(&self) -> TreeBreadthFirstIterator<T> {
73        TreeBreadthFirstIterator {
74            queue: vec![self].into_iter().collect(),
75        }
76    }
77}
78
79/// Implement the `TreeIterator` trait for `Tree`
80///
81/// This allows for traversal of the entire tree in pre-order, post-order, and breadth-first order.
82impl<T> TreeIterator<T> for Tree<T> {
83    fn iter_pre_order(&self) -> PreOrderIterator<T> {
84        PreOrderIterator {
85            stack: self
86                .root()
87                .map_or(Vec::new(), |root| vec![root].into_iter().collect()),
88        }
89    }
90
91    fn iter_post_order(&self) -> PostOrderIterator<T> {
92        PostOrderIterator {
93            stack: self
94                .root()
95                .map_or(Vec::new(), |root| vec![(root, false)].into_iter().collect()),
96        }
97    }
98    fn iter_breadth_first(&self) -> TreeBreadthFirstIterator<T> {
99        TreeBreadthFirstIterator {
100            queue: self
101                .root()
102                .map_or(VecDeque::new(), |root| vec![root].into_iter().collect()),
103        }
104    }
105}
106
107pub struct PreOrderIterator<'a, T> {
108    stack: Vec<&'a TreeNode<T>>,
109}
110
111impl<'a, T> Iterator for PreOrderIterator<'a, T> {
112    type Item = &'a TreeNode<T>;
113
114    fn next(&mut self) -> Option<Self::Item> {
115        self.stack.pop().map(|node| {
116            // Push children in reverse order for correct traversal
117            if let Some(children) = node.children() {
118                for child in children.iter().rev() {
119                    self.stack.push(child);
120                }
121            }
122            node
123        })
124    }
125}
126
127pub struct PostOrderIterator<'a, T> {
128    stack: Vec<(&'a TreeNode<T>, bool)>,
129}
130
131impl<'a, T> Iterator for PostOrderIterator<'a, T> {
132    type Item = &'a TreeNode<T>;
133
134    fn next(&mut self) -> Option<Self::Item> {
135        while let Some((node, visited)) = self.stack.pop() {
136            if visited {
137                return Some(node);
138            }
139            self.stack.push((node, true));
140            if let Some(children) = node.children() {
141                for child in children.iter().rev() {
142                    self.stack.push((child, false));
143                }
144            }
145        }
146        None
147    }
148}
149
150pub struct TreeBreadthFirstIterator<'a, T> {
151    queue: VecDeque<&'a TreeNode<T>>,
152}
153
154impl<'a, T> Iterator for TreeBreadthFirstIterator<'a, T> {
155    type Item = &'a TreeNode<T>;
156
157    fn next(&mut self) -> Option<Self::Item> {
158        let node = self.queue.pop_front()?;
159        if let Some(children) = node.children() {
160            self.queue.extend(children.iter());
161        }
162        Some(node)
163    }
164}
165
166#[cfg(test)]
167mod tests {
168    use super::*;
169    use crate::collections::{Tree, TreeNode};
170
171    use crate::Op;
172    use crate::node::Node;
173    use crate::ops::operation;
174
175    #[test]
176    fn test_tree_traversal() {
177        // Create a simple tree:
178        //       1
179        //      / \
180        //     2   3
181        //    /
182        //   4
183        let leaf = Op::constant(4.0);
184        let node2 = TreeNode::with_children(Op::constant(2.0), vec![TreeNode::new(leaf)]);
185
186        let node3 = TreeNode::new(Op::constant(3.0));
187
188        let root = Tree::new(TreeNode::with_children(
189            Op::constant(1.0),
190            vec![node2, node3],
191        ));
192
193        // Test pre-order
194        let pre_order: Vec<f32> = root
195            .iter_pre_order()
196            .map(|n| match &n.value() {
197                operation::Op::Const(_, v) => *v,
198                _ => panic!("Expected constant but got {:?}", n.value()),
199            })
200            .collect();
201        assert_eq!(pre_order, vec![1.0, 2.0, 4.0, 3.0]);
202
203        // Test post-order
204        let post_order: Vec<f32> = root
205            .iter_post_order()
206            .map(|n| match &n.value() {
207                operation::Op::Const(_, v) => *v,
208                _ => panic!("Expected constant"),
209            })
210            .collect();
211        assert_eq!(post_order, vec![4.0, 2.0, 3.0, 1.0]);
212
213        // Test breadth-first
214        let bfs: Vec<f32> = root
215            .iter_breadth_first()
216            .map(|n| match &n.value() {
217                operation::Op::Const(_, v) => *v,
218                _ => panic!("Expected constant"),
219            })
220            .collect();
221        assert_eq!(bfs, vec![1.0, 2.0, 3.0, 4.0]);
222    }
223}