use std::{collections::VecDeque, marker::PhantomData};
use crate::traversal_order::{BreadthFirst, DepthFirst, TraversalOrder};
pub trait TreeNode {
fn children(&self) -> impl DoubleEndedIterator<Item = &Self>;
fn iter<T: TraversalOrder>(&self) -> TreeIter<'_, Self, T>
where
Self: Sized,
{
TreeIter::new([self])
}
}
#[derive(Debug)]
pub struct TreeIter<'a, N, T> {
nodes: VecDeque<&'a N>,
_order: PhantomData<T>,
}
impl<'a, N, T: TraversalOrder> TreeIter<'a, N, T> {
pub fn new(roots: impl IntoIterator<Item = &'a N>) -> Self {
Self {
nodes: roots.into_iter().collect(),
_order: PhantomData,
}
}
}
impl<'a, N: TreeNode> Iterator for TreeIter<'a, N, BreadthFirst> {
type Item = &'a N;
fn next(&mut self) -> Option<Self::Item> {
let node = self.nodes.pop_front()?;
self.nodes.extend(node.children());
Some(node)
}
}
impl<'a, N: TreeNode> Iterator for TreeIter<'a, N, DepthFirst> {
type Item = &'a N;
fn next(&mut self) -> Option<Self::Item> {
let node = self.nodes.pop_front()?;
for child in node.children().rev() {
self.nodes.push_front(child);
}
Some(node)
}
}