ntree_rs/traversal/traverse/
mod.rs1#[cfg(feature = "async")]
4mod r#async;
5#[cfg(feature = "async")]
6pub use r#async::*;
7
8mod sync;
9pub use sync::*;
10
11use crate::Node;
12use std::marker::PhantomData;
13
14pub struct Traverse<'a, T, S> {
16 node: &'a Node<T>,
17 strategy: PhantomData<S>,
18}
19
20impl<'a, T, S> From<&'a Node<T>> for Traverse<'a, T, S> {
21 fn from(node: &'a Node<T>) -> Self {
22 Self {
23 node,
24 strategy: PhantomData,
25 }
26 }
27}
28
29impl<'a, T, S> Traverse<'a, T, S> {
30 pub fn node(&self) -> &Node<T> {
31 self.node
32 }
33
34 pub fn pre(self) -> InPre<'a, T, S> {
36 InPre {
37 node: self.node,
38 next: vec![self.node],
39 strategy: PhantomData,
40 }
41 }
42
43 pub fn post(self) -> InPost<'a, T, S> {
45 InPost {
46 node: self.node,
47 next: vec![(self.node, 0)],
48 strategy: PhantomData,
49 }
50 }
51}
52
53pub struct InPre<'a, T, S> {
55 node: &'a Node<T>,
56 next: Vec<&'a Node<T>>,
57 strategy: PhantomData<S>,
58}
59
60impl<'a, T, S> Iterator for InPre<'a, T, S> {
61 type Item = &'a Node<T>;
62
63 fn next(&mut self) -> Option<Self::Item> {
64 let current = self.next.pop()?;
65 self.next.extend(current.children.iter().rev());
66 Some(current)
67 }
68}
69
70impl<'a, T, S> InPre<'a, T, S> {
71 pub fn iter(self) -> impl Iterator<Item = &'a Node<T>> {
72 self
73 }
74}
75
76pub struct InPost<'a, T, S> {
78 node: &'a Node<T>,
79 next: Vec<(&'a Node<T>, usize)>,
80 strategy: PhantomData<S>,
81}
82
83impl<'a, T, S> Iterator for InPost<'a, T, S> {
84 type Item = &'a Node<T>;
85
86 fn next(&mut self) -> Option<Self::Item> {
87 let (parent, next_child) = *self.next.last()?;
88 if let Some(next_child) = parent.children.get(next_child) {
89 self.next.last_mut()?.1 += 1;
90 self.next.push((next_child, 0));
91 return self.next();
92 }
93
94 self.next.pop().map(|(parent, _)| parent)
95 }
96}
97
98impl<'a, T, S> InPost<'a, T, S> {
99 pub fn iter(self) -> impl Iterator<Item = &'a Node<T>> {
100 self
101 }
102}
103
104pub struct PrePost<'a, T, R, F, S> {
106 node: &'a Node<T>,
107 pre: F,
108 r: PhantomData<R>,
109 strategy: PhantomData<S>,
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115 use crate::node;
116
117 #[test]
118 fn test_pre_order_traversal() {
119 let root = node!(
120 10,
121 node!(20, node!(40), node!(50), node!(60)),
122 node!(30, node!(70), node!(80))
123 );
124
125 let mut result = Vec::new();
126 root.traverse()
127 .pre()
128 .iter()
129 .for_each(|n| result.push(n.value));
130
131 assert_eq!(result, vec![10, 20, 40, 50, 60, 30, 70, 80]);
132 }
133
134 #[test]
135 fn test_post_order_traversal() {
136 let root = node!(
137 10,
138 node!(20, node!(40), node!(50), node!(60)),
139 node!(30, node!(70), node!(80))
140 );
141
142 let mut result = Vec::new();
143 root.traverse()
144 .post()
145 .iter()
146 .for_each(|n| result.push(n.value));
147
148 assert_eq!(result, vec![40, 50, 60, 20, 70, 80, 30, 10]);
149 }
150}