catlog/dbl/
tree_algorithms.rs1use ego_tree::iter::{Descendants, Edge};
4use ego_tree::{NodeId, NodeRef, Tree};
5use std::collections::VecDeque;
6
7pub trait TreeTraversal<T> {
9 fn dfs<'a>(&'a self) -> Descendants<'a, T>
11 where
12 T: 'a;
13
14 fn bfs<'a>(&'a self) -> BreadthFirstTraversal<'a, T>
16 where
17 T: 'a;
18}
19
20pub struct BreadthFirstTraversal<'a, T: 'a> {
22 tree: &'a Tree<T>,
23 queue: VecDeque<(NodeId, usize)>,
24 current_level: usize,
25}
26
27impl<'a, T: 'a> BreadthFirstTraversal<'a, T> {
28 pub fn starting_at(root: NodeRef<'a, T>) -> Self {
30 let tree = root.tree();
31 let mut queue = VecDeque::new();
32 queue.push_back((root.id(), 1));
33 Self {
34 tree,
35 queue,
36 current_level: 0,
37 }
38 }
39
40 pub fn peek_at_same_level(&self) -> Option<NodeRef<'a, T>> {
42 self.queue.front().and_then(|(id, level)| {
43 if *level == self.current_level {
44 self.tree.get(*id)
45 } else {
46 None
47 }
48 })
49 }
50}
51
52impl<'a, T: 'a> Iterator for BreadthFirstTraversal<'a, T> {
53 type Item = NodeRef<'a, T>;
54
55 fn next(&mut self) -> Option<Self::Item> {
56 let (id, level) = self.queue.pop_front()?;
57 self.current_level = level;
58 let node = self.tree.get(id).unwrap();
59 for child in node.children() {
60 self.queue.push_back((child.id(), level + 1));
61 }
62 Some(node)
63 }
64}
65
66impl<'a, T: 'a> std::iter::FusedIterator for BreadthFirstTraversal<'a, T> {}
67
68impl<T> TreeTraversal<T> for Tree<T> {
69 fn dfs<'a>(&'a self) -> Descendants<'a, T>
72 where
73 T: 'a,
74 {
75 self.root().descendants()
76 }
77
78 fn bfs<'a>(&'a self) -> BreadthFirstTraversal<'a, T>
80 where
81 T: 'a,
82 {
83 BreadthFirstTraversal::starting_at(self.root())
84 }
85}
86
87pub trait TreeIsomorphism<T> {
89 fn is_isomorphic_to(&self, other: &Self) -> bool;
97}
98
99impl<T> TreeIsomorphism<T> for Tree<T>
100where
101 T: Eq,
102{
103 fn is_isomorphic_to(&self, other: &Self) -> bool {
104 let mut self_traversal = self.root().traverse();
105 let mut other_traversal = other.root().traverse();
106 loop {
107 match (self_traversal.next(), other_traversal.next()) {
108 (Some(Edge::Open(n1)), Some(Edge::Open(n2))) if n1.value() == n2.value() => {}
109 (Some(Edge::Close(n1)), Some(Edge::Close(n2))) if n1.value() == n2.value() => {}
110 (None, None) => {
111 break;
112 }
113 _ => {
114 return false;
115 }
116 }
117 }
118 true
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125 use ego_tree::tree;
126
127 #[test]
128 fn dfs() {
129 let tree = tree!('a' => { 'b' => { 'd', 'e' }, 'c' });
130 let values: Vec<_> = tree.dfs().map(|node| *node.value()).collect();
131 assert_eq!(values, vec!['a', 'b', 'd', 'e', 'c']);
132 }
133
134 #[test]
135 fn bfs() {
136 let tree = tree!('a' => { 'b' => { 'd', 'e' }, 'c' });
137 let values: Vec<_> = tree.bfs().map(|node| *node.value()).collect();
138 assert_eq!(values, vec!['a', 'b', 'c', 'd', 'e']);
139
140 let tree = tree!('a' => { 'b' => {'d'}, 'c' => {'e'} });
141 let mut traverse = tree.bfs();
142 traverse.next();
143 assert!(traverse.peek_at_same_level().is_none());
144 assert_eq!(traverse.nth(2).map(|node| *node.value()), Some('d'));
145 assert_eq!(traverse.peek_at_same_level().map(|node| *node.value()), Some('e'));
146 }
147
148 #[test]
149 fn isomorphism() {
150 let tree = tree!('a' => { 'b' => { 'd', 'e' }, 'c' });
151 assert!(tree.is_isomorphic_to(&tree));
152
153 let other = tree!('a' => { 'b' => { 'd' }, 'e' => { 'c' }});
154 let tree_dfs_values: Vec<_> = tree.dfs().map(|node| *node.value()).collect();
155 let other_dfs_values: Vec<_> = other.dfs().map(|node| *node.value()).collect();
156 assert_eq!(tree_dfs_values, other_dfs_values);
157 assert!(!tree.is_isomorphic_to(&other));
158 }
159}