catlog/one/
tree_algorithms.rs1use ego_tree::iter::{Descendants, Edge};
4use ego_tree::{NodeId, NodeRef, Tree};
5use itertools::{EitherOrBoth::Both, Itertools};
6use std::collections::VecDeque;
7
8pub trait TreeTraversal<T> {
10 fn dfs(&self) -> Descendants<'_, T>;
12
13 fn bfs(&self) -> BreadthFirstTraversal<'_, T>;
15
16 fn left_boundary(&self) -> impl Iterator<Item = Self>;
18
19 fn right_boundary(&self) -> impl Iterator<Item = Self>;
21}
22
23pub struct BreadthFirstTraversal<'a, T: 'a> {
25 tree: &'a Tree<T>,
26 queue: VecDeque<(NodeId, usize)>,
27 current_level: usize,
28}
29
30impl<'a, T: 'a> BreadthFirstTraversal<'a, T> {
31 pub fn starting_at(root: NodeRef<'a, T>) -> Self {
33 let tree = root.tree();
34 let mut queue = VecDeque::new();
35 queue.push_back((root.id(), 1));
36 Self {
37 tree,
38 queue,
39 current_level: 0,
40 }
41 }
42
43 pub fn peek_at_same_level(&self) -> Option<NodeRef<'a, T>> {
45 self.queue.front().and_then(|(id, level)| {
46 if *level == self.current_level {
47 self.tree.get(*id)
48 } else {
49 None
50 }
51 })
52 }
53}
54
55impl<'a, T: 'a> Iterator for BreadthFirstTraversal<'a, T> {
56 type Item = NodeRef<'a, T>;
57
58 fn next(&mut self) -> Option<Self::Item> {
59 let (id, level) = self.queue.pop_front()?;
60 self.current_level = level;
61 let node = self.tree.get(id).unwrap();
62 for child in node.children() {
63 self.queue.push_back((child.id(), level + 1));
64 }
65 Some(node)
66 }
67}
68
69impl<'a, T: 'a> std::iter::FusedIterator for BreadthFirstTraversal<'a, T> {}
70
71impl<'a, T: 'a> TreeTraversal<T> for NodeRef<'a, T> {
72 fn dfs(&self) -> Descendants<'a, T> {
75 self.descendants()
76 }
77
78 fn bfs(&self) -> BreadthFirstTraversal<'a, T> {
80 BreadthFirstTraversal::starting_at(*self)
81 }
82
83 fn left_boundary(&self) -> impl Iterator<Item = Self> {
84 let mut maybe_node = Some(*self);
85 std::iter::from_fn(move || {
86 let prev = maybe_node;
87 maybe_node = maybe_node.and_then(|node| node.first_child());
88 prev
89 })
90 }
91
92 fn right_boundary(&self) -> impl Iterator<Item = Self> {
93 let mut maybe_node = Some(*self);
94 std::iter::from_fn(move || {
95 let prev = maybe_node;
96 maybe_node = maybe_node.and_then(|node| node.last_child());
97 prev
98 })
99 }
100}
101
102pub trait TreeIsomorphism<T> {
104 fn is_isomorphic_to(&self, other: &Self) -> bool;
115}
116
117impl<T> TreeIsomorphism<T> for Tree<T>
118where
119 T: Eq,
120{
121 fn is_isomorphic_to(&self, other: &Self) -> bool {
122 self.root()
123 .traverse()
124 .zip_longest(other.root().traverse())
125 .all(|pair| match pair {
126 Both(Edge::Open(n1), Edge::Open(n2)) | Both(Edge::Close(n1), Edge::Close(n2)) => {
127 n1.value() == n2.value()
128 }
129 _ => false,
130 })
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137 use ego_tree::tree;
138
139 #[test]
140 fn dfs() {
141 let tree = tree!('a' => { 'b' => { 'd', 'e' }, 'c' });
142 let values: Vec<_> = tree.root().dfs().map(|node| *node.value()).collect();
143 assert_eq!(values, vec!['a', 'b', 'd', 'e', 'c']);
144 }
145
146 #[test]
147 fn bfs() {
148 let tree = tree!('a' => { 'b' => { 'd', 'e' }, 'c' });
149 let values: Vec<_> = tree.root().bfs().map(|node| *node.value()).collect();
150 assert_eq!(values, vec!['a', 'b', 'c', 'd', 'e']);
151
152 let tree = tree!('a' => { 'b' => {'d'}, 'c' => {'e'} });
153 let root = tree.root();
154 let mut traverse = root.bfs();
155 traverse.next();
156 assert!(traverse.peek_at_same_level().is_none());
157 assert_eq!(traverse.nth(2).map(|node| *node.value()), Some('d'));
158 assert_eq!(traverse.peek_at_same_level().map(|node| *node.value()), Some('e'));
159 }
160
161 #[test]
162 fn isomorphism() {
163 let tree = tree!('a' => { 'b' => { 'd', 'e' }, 'c' });
164 assert!(tree.is_isomorphic_to(&tree));
165
166 let other = tree!('a' => { 'b' => { 'd' }, 'e' => { 'c' }});
167 let tree_dfs_values: Vec<_> = tree.root().dfs().map(|node| *node.value()).collect();
168 let other_dfs_values: Vec<_> = other.root().dfs().map(|node| *node.value()).collect();
169 assert_eq!(tree_dfs_values, other_dfs_values);
170 assert!(!tree.is_isomorphic_to(&other));
171 }
172}