use crate::tree::Tree;
impl Tree {
pub fn pre_order(&self) -> PreOrder<'_> {
PreOrder::new(self)
}
pub fn post_order(&self) -> PostOrder<'_> {
PostOrder::new(self)
}
pub fn level_order(&self) -> LevelOrder<'_> {
LevelOrder::new(self)
}
pub fn nodes(&self) -> Nodes<'_> {
Nodes::new(self)
}
pub fn leaves(&self) -> Leaves<'_> {
Leaves::new(self)
}
}
pub struct PreOrder<'a> {
stack: Vec<&'a Tree>,
}
impl<'a> PreOrder<'a> {
pub fn new(tree: &'a Tree) -> Self {
PreOrder { stack: vec![tree] }
}
}
impl<'a> Iterator for PreOrder<'a> {
type Item = &'a Tree;
fn next(&mut self) -> Option<Self::Item> {
self.stack.pop().inspect(|tree| {
if let Tree::Node(_, children) = tree {
for child in children.iter().rev() {
self.stack.push(child);
}
}
})
}
}
pub struct PostOrder<'a> {
stack: Vec<(bool, &'a Tree)>,
}
impl<'a> PostOrder<'a> {
pub fn new(tree: &'a Tree) -> Self {
PostOrder {
stack: vec![(false, tree)],
}
}
}
impl<'a> Iterator for PostOrder<'a> {
type Item = &'a Tree;
fn next(&mut self) -> Option<Self::Item> {
while let Some((visited, tree)) = self.stack.pop() {
if visited {
return Some(tree);
}
self.stack.push((true, tree));
if let Tree::Node(_, children) = tree {
for child in children.iter().rev() {
self.stack.push((false, child));
}
}
}
None
}
}
pub struct LevelOrder<'a> {
queue: std::collections::VecDeque<&'a Tree>,
}
impl<'a> LevelOrder<'a> {
pub fn new(tree: &'a Tree) -> Self {
let mut queue = std::collections::VecDeque::new();
queue.push_back(tree);
LevelOrder { queue }
}
}
impl<'a> Iterator for LevelOrder<'a> {
type Item = &'a Tree;
fn next(&mut self) -> Option<Self::Item> {
self.queue.pop_front().inspect(|tree| {
if let Tree::Node(_, children) = tree {
for child in children {
self.queue.push_back(child);
}
}
})
}
}
pub struct Nodes<'a> {
inner: PreOrder<'a>,
}
impl<'a> Nodes<'a> {
pub fn new(tree: &'a Tree) -> Self {
Nodes {
inner: PreOrder::new(tree),
}
}
}
impl<'a> Iterator for Nodes<'a> {
type Item = &'a Tree;
fn next(&mut self) -> Option<Self::Item> {
self.inner.find(|tree| tree.is_node())
}
}
pub struct Leaves<'a> {
inner: PreOrder<'a>,
}
impl<'a> Leaves<'a> {
pub fn new(tree: &'a Tree) -> Self {
Leaves {
inner: PreOrder::new(tree),
}
}
}
impl<'a> Iterator for Leaves<'a> {
type Item = &'a Tree;
fn next(&mut self) -> Option<Self::Item> {
self.inner.find(|tree| tree.is_leaf())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pre_order() {
let tree = Tree::Node(
"root".to_string(),
vec![
Tree::Node("a".to_string(), vec![Tree::Leaf(vec!["a1".to_string()])]),
Tree::Leaf(vec!["b".to_string()]),
],
);
let nodes: Vec<_> = PreOrder::new(&tree).collect();
assert_eq!(nodes.len(), 4);
assert_eq!(nodes[0].label(), Some("root"));
}
#[test]
fn test_post_order() {
let tree = Tree::Node(
"root".to_string(),
vec![
Tree::Node("a".to_string(), vec![Tree::Leaf(vec!["a1".to_string()])]),
Tree::Leaf(vec!["b".to_string()]),
],
);
let nodes: Vec<_> = PostOrder::new(&tree).collect();
assert_eq!(nodes.len(), 4);
assert_eq!(nodes[3].label(), Some("root"));
}
#[test]
fn test_level_order() {
let tree = Tree::Node(
"root".to_string(),
vec![
Tree::Node("a".to_string(), vec![Tree::Leaf(vec!["a1".to_string()])]),
Tree::Leaf(vec!["b".to_string()]),
],
);
let nodes: Vec<_> = LevelOrder::new(&tree).collect();
assert_eq!(nodes.len(), 4);
assert_eq!(nodes[0].label(), Some("root"));
}
#[test]
fn test_nodes() {
let tree = Tree::Node(
"root".to_string(),
vec![
Tree::Node("a".to_string(), vec![Tree::Leaf(vec!["a1".to_string()])]),
Tree::Leaf(vec!["b".to_string()]),
],
);
let nodes: Vec<_> = Nodes::new(&tree).collect();
assert_eq!(nodes.len(), 2);
assert!(nodes.iter().all(|n| n.is_node()));
}
#[test]
fn test_leaves() {
let tree = Tree::Node(
"root".to_string(),
vec![
Tree::Node("a".to_string(), vec![Tree::Leaf(vec!["a1".to_string()])]),
Tree::Leaf(vec!["b".to_string()]),
],
);
let leaves: Vec<_> = Leaves::new(&tree).collect();
assert_eq!(leaves.len(), 2);
assert!(leaves.iter().all(|l| l.is_leaf()));
}
}