use std::collections::VecDeque;
use std::iter::FusedIterator;
#[allow(missing_debug_implementations)]
#[derive(Clone)]
pub struct DftPreRev<'a, T, F, I>
where
T: ?Sized,
F: FnMut(&'a T) -> I,
I: Iterator<Item = &'a T>,
{
visited: usize,
current_depth: usize,
queue: VecDeque<(usize, &'a T)>,
iter_children: F,
}
impl<'a, T, F, I> DftPreRev<'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 {
visited: 0,
current_depth: 0,
queue: VecDeque::from(vec![(0, root)]),
iter_children,
}
}
}
impl<'a, T, F, I> Iterator for DftPreRev<'a, T, F, I>
where
T: ?Sized,
F: FnMut(&'a T) -> I,
I: Iterator<Item = &'a T>,
{
type Item = (usize, &'a T);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.queue.is_empty() {
None
} else {
loop {
let i = self.visited;
let (depth, node) = if let Some(&node) = self.queue.get(i) {
node
} else {
break;
};
if self.current_depth > depth {
break;
}
let before_len = self.queue.len();
for child in (self.iter_children)(node) {
self.queue.insert(i + 1, (depth + 1, child));
}
self.visited += 1;
self.current_depth = depth;
if self.queue.len() == before_len {
break;
}
}
let node = self.queue.remove(self.visited - 1).unwrap();
self.visited -= 1;
self.current_depth = node.0;
Some(node)
}
}
}
impl<'a, T, F, I> FusedIterator for DftPreRev<'a, T, F, I>
where
T: ?Sized,
F: FnMut(&'a T) -> I,
I: Iterator<Item = &'a T>,
{
}
#[cfg(test)]
mod tests {
use crate::DftPre;
use super::*;
#[derive(PartialEq, Debug)]
struct Node(&'static str, &'static [Node]);
#[rustfmt::skip]
const TREE: Node = Node("I", &[
Node("H", &[
Node("G", &[]),
Node("F", &[
Node("E", &[])
])]),
Node("D", &[
Node("C", &[
Node("B", &[])
]),
Node("A", &[])]),
]);
#[test]
fn dft_pre_rev() {
let iter = DftPreRev::new(&TREE, |node| node.1.iter());
let mut iter = iter.map(|(depth, node)| (depth, node.0));
assert_eq!(iter.next(), Some((2, "A")));
assert_eq!(iter.next(), Some((3, "B")));
assert_eq!(iter.next(), Some((2, "C")));
assert_eq!(iter.next(), Some((1, "D")));
assert_eq!(iter.next(), Some((3, "E")));
assert_eq!(iter.next(), Some((2, "F")));
assert_eq!(iter.next(), Some((2, "G")));
assert_eq!(iter.next(), Some((1, "H")));
assert_eq!(iter.next(), Some((0, "I")));
assert_eq!(iter.next(), None);
}
#[test]
fn dft_pre() {
let mut iter1 = DftPreRev::new(&TREE, |node| node.1.iter());
let iter2 = DftPre::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);
}
}
}