use std::iter::{Extend, FusedIterator};
#[allow(missing_debug_implementations)]
#[derive(Clone)]
pub struct DftPostRev<'a, T, F, I>
where
T: ?Sized,
F: FnMut(&'a T) -> I,
I: Iterator<Item = &'a T>,
{
queue: Vec<(usize, &'a T)>,
iter_children: F,
}
impl<'a, T, F, I> DftPostRev<'a, T, F, I>
where
T: ?Sized,
F: FnMut(&'a T) -> I,
I: Iterator<Item = &'a T>,
{
#[inline]
pub fn new(root: &'a T, iter_children: F) -> Self {
Self {
queue: vec![(0, root)],
iter_children,
}
}
}
impl<'a, T, F, I> Iterator for DftPostRev<'a, T, F, I>
where
T: ?Sized,
F: FnMut(&'a T) -> I,
I: Iterator<Item = &'a T>,
{
type Item = (usize, &'a T);
fn next(&mut self) -> Option<Self::Item> {
if let Some((depth, node)) = self.queue.pop() {
let children = (self.iter_children)(node);
self.queue.extend(children.map(|child| (depth + 1, child)));
Some((depth, node))
} else {
None
}
}
}
impl<'a, T, F, I> FusedIterator for DftPostRev<'a, T, F, I>
where
T: ?Sized,
F: FnMut(&'a T) -> I,
I: Iterator<Item = &'a T>,
{
}
#[cfg(test)]
mod tests {
use crate::DftPost;
use super::*;
#[derive(PartialEq, Debug)]
struct Node(&'static str, &'static [Node]);
#[rustfmt::skip]
const TREE: Node = Node("A", &[
Node("F", &[
Node("I", &[]),
Node("G", &[
Node("H", &[])
])]),
Node("B", &[
Node("D", &[
Node("E", &[])
]),
Node("C", &[])]),
]);
#[test]
fn dft_post_rev() {
let iter = DftPostRev::new(&TREE, |node| node.1.iter());
let mut iter = iter.map(|(depth, node)| (depth, node.0));
assert_eq!(iter.next(), Some((0, "A")));
assert_eq!(iter.next(), Some((1, "B")));
assert_eq!(iter.next(), Some((2, "C")));
assert_eq!(iter.next(), Some((2, "D")));
assert_eq!(iter.next(), Some((3, "E")));
assert_eq!(iter.next(), Some((1, "F")));
assert_eq!(iter.next(), Some((2, "G")));
assert_eq!(iter.next(), Some((3, "H")));
assert_eq!(iter.next(), Some((2, "I")));
assert_eq!(iter.next(), None);
}
#[test]
fn dft_post() {
let mut iter1 = DftPostRev::new(&TREE, |node| node.1.iter());
let iter2 = DftPost::new(&TREE, |node| node.1.iter()).collect::<Vec<_>>();
let mut iter2 = iter2.into_iter().rev();
loop {
let next1 = iter1.next();
let next2 = iter2.next();
if next1.is_none() && next2.is_none() {
break;
}
assert_eq!(next1, next2);
}
}
}