diff --git a/src/leaves_iterators/borrow.rs b/src/leaves_iterators/borrow.rs new file mode 100644 index 0000000..6e8479d --- /dev/null +++ b/src/leaves_iterators/borrow.rs @@ -0,0 +1,81 @@ +use crate::prelude::{BorrowedTreeNode, BinaryChildren, BorrowedBinaryTreeNode}; +use crate::make_peekable_iterator::MakePeekableIterator; + +use super::dfs_preorder_next_with_children_check; + +pub struct BorrowedLeavesIterator<'a, Node> + where Node: BorrowedTreeNode<'a> { + + root: Option<&'a Node>, + traversal_stack: Vec>, + +} + +impl<'a, Node> BorrowedLeavesIterator<'a, Node> + where Node: BorrowedTreeNode<'a> { + + pub (crate) fn new(root: &'a Node) -> BorrowedLeavesIterator<'a, Node> { + BorrowedLeavesIterator { + root: Some(root), + traversal_stack: Vec::new() + } + } + + dfs_preorder_next_with_children_check!(get_value_and_children_iter, Node::BorrowedValue); +} + +impl<'a, Node> Iterator for BorrowedLeavesIterator<'a, Node> + where Node: BorrowedTreeNode<'a> { + + type Item = Node::BorrowedValue; + fn next(&mut self) -> Option { + loop { + let value = self.dfs_preorder_next(); + match value { + None => return None, + Some(value) => { + if value.0 { continue; } + return Some(value.1); + } + } + } + } +} + +pub struct BorrowedBinaryLeavesIterator<'a, Node> + where Node: BorrowedBinaryTreeNode<'a> { + + root: Option<&'a Node>, + traversal_stack: Vec>>, +} + +impl<'a, Node> BorrowedBinaryLeavesIterator<'a, Node> + where Node: BorrowedBinaryTreeNode<'a> { + + pub (crate) fn new(root: &'a Node) -> BorrowedBinaryLeavesIterator<'a, Node> { + BorrowedBinaryLeavesIterator { + root: Some(root), + traversal_stack: Vec::new() + } + } + + dfs_preorder_next_with_children_check!(get_value_and_children_iter, Node::BorrowedValue); +} + +impl<'a, Node> Iterator for BorrowedBinaryLeavesIterator<'a, Node> + where Node: BorrowedBinaryTreeNode<'a> { + + type Item = Node::BorrowedValue; + fn next(&mut self) -> Option { + loop { + let value = self.dfs_preorder_next(); + match value { + None => return None, + Some(value) => { + if value.0 { continue; } + return Some(value.1); + } + } + } + } +} \ No newline at end of file diff --git a/src/leaves_iterators/mod.rs b/src/leaves_iterators/mod.rs new file mode 100644 index 0000000..7522e30 --- /dev/null +++ b/src/leaves_iterators/mod.rs @@ -0,0 +1,70 @@ +pub (crate) mod owned; +pub (crate) mod mut_borrow; +pub (crate) mod borrow; + +macro_rules! dfs_preorder_next_with_children_check { + ($get_value_and_children: ident, $value_type: ty) => { + fn dfs_preorder_next(&mut self) -> Option<(bool, $value_type)> { + match std::mem::take(&mut self.root) { + Some(next) => { + let (value, children) = next.$get_value_and_children(); + let mut has_children = false; + match children { + None => {} + Some(children) => { + let mut peekable = MakePeekableIterator::new(children); + has_children = peekable.peek().is_some(); + self.traversal_stack.push(peekable); + } + } + return Some((has_children, value)); + } + None => { + let next; + loop { + let stack_len = self.traversal_stack.len(); + if stack_len == 0 { + next = None; + break; + } + match self.traversal_stack.get_mut(stack_len - 1) { + None => { + next = None; + break; + } + Some(top) => { + match top.next() { + None => { + self.traversal_stack.pop(); + } + Some(value) => { + next = Some(value); + break; + } + } + } + } + }; + match next { + None => return None, + Some(node) => { + let (value, children) = node.$get_value_and_children(); + let mut has_children = false; + match children { + None => {} + Some(children) => { + let mut peekable = MakePeekableIterator::new(children); + has_children = peekable.peek().is_some(); + self.traversal_stack.push(peekable); + } + } + return Some((has_children, value)); + } + } + } + } + } + }; +} + +pub (crate) use dfs_preorder_next_with_children_check; \ No newline at end of file diff --git a/src/leaves_iterators/mut_borrow.rs b/src/leaves_iterators/mut_borrow.rs new file mode 100644 index 0000000..8e097d8 --- /dev/null +++ b/src/leaves_iterators/mut_borrow.rs @@ -0,0 +1,80 @@ +use crate::prelude::{MutBorrowedTreeNode, BinaryChildren, MutBorrowedBinaryTreeNode}; +use crate::make_peekable_iterator::MakePeekableIterator; + +use super::dfs_preorder_next_with_children_check; + +pub struct MutBorrowedLeavesIterator<'a, Node> + where Node: MutBorrowedTreeNode<'a> { + + root: Option<&'a mut Node>, + traversal_stack: Vec>, +} + +impl<'a, Node> MutBorrowedLeavesIterator<'a, Node> + where Node: MutBorrowedTreeNode<'a> { + + pub (crate) fn new(root: &'a mut Node) -> MutBorrowedLeavesIterator<'a, Node> { + MutBorrowedLeavesIterator { + root: Some(root), + traversal_stack: Vec::new() + } + } + + dfs_preorder_next_with_children_check!(get_value_and_children_iter_mut, Node::MutBorrowedValue); +} + +impl<'a, Node> Iterator for MutBorrowedLeavesIterator<'a, Node> + where Node: MutBorrowedTreeNode<'a> { + + type Item = Node::MutBorrowedValue; + fn next(&mut self) -> Option { + loop { + let value = self.dfs_preorder_next(); + match value { + None => return None, + Some(value) => { + if value.0 { continue; } + return Some(value.1); + } + } + } + } +} + +pub struct MutBorrowedBinaryLeavesIterator<'a, Node> + where Node: MutBorrowedBinaryTreeNode<'a> { + + root: Option<&'a mut Node>, + traversal_stack: Vec>>, +} + +impl<'a, Node> MutBorrowedBinaryLeavesIterator<'a, Node> + where Node: MutBorrowedBinaryTreeNode<'a> { + + pub (crate) fn new(root: &'a mut Node) -> MutBorrowedBinaryLeavesIterator<'a, Node> { + MutBorrowedBinaryLeavesIterator { + root: Some(root), + traversal_stack: Vec::new() + } + } + + dfs_preorder_next_with_children_check!(get_value_and_children_iter_mut, Node::MutBorrowedValue); +} + +impl<'a, Node> Iterator for MutBorrowedBinaryLeavesIterator<'a, Node> + where Node: MutBorrowedBinaryTreeNode<'a> { + + type Item = Node::MutBorrowedValue; + fn next(&mut self) -> Option { + loop { + let value = self.dfs_preorder_next(); + match value { + None => return None, + Some(value) => { + if value.0 { continue; } + return Some(value.1); + } + } + } + } +} \ No newline at end of file diff --git a/src/leaves_iterators/owned.rs b/src/leaves_iterators/owned.rs new file mode 100644 index 0000000..71b3d9b --- /dev/null +++ b/src/leaves_iterators/owned.rs @@ -0,0 +1,80 @@ +use crate::prelude::{OwnedTreeNode, BinaryChildren, OwnedBinaryTreeNode}; +use crate::make_peekable_iterator::MakePeekableIterator; + +use super::dfs_preorder_next_with_children_check; + +pub struct OwnedLeavesIterator + where Node: OwnedTreeNode { + + root: Option, + traversal_stack: Vec>, +} + +impl<'a, Node> OwnedLeavesIterator + where Node: OwnedTreeNode { + + pub (crate) fn new(root: Node) -> OwnedLeavesIterator { + OwnedLeavesIterator { + root: Some(root), + traversal_stack: Vec::new() + } + } + + dfs_preorder_next_with_children_check!(get_value_and_children, Node::OwnedValue); +} + +impl<'a, Node> Iterator for OwnedLeavesIterator + where Node: OwnedTreeNode { + + type Item = Node::OwnedValue; + fn next(&mut self) -> Option { + loop { + let value = self.dfs_preorder_next(); + match value { + None => return None, + Some(value) => { + if value.0 { continue; } + return Some(value.1); + } + } + } + } +} + +pub struct OwnedBinaryLeavesIterator + where Node: OwnedBinaryTreeNode { + + root: Option, + traversal_stack: Vec>>, +} + +impl<'a, Node> OwnedBinaryLeavesIterator + where Node: OwnedBinaryTreeNode { + + pub (crate) fn new(root: Node) -> OwnedBinaryLeavesIterator { + OwnedBinaryLeavesIterator { + root: Some(root), + traversal_stack: Vec::new() + } + } + + dfs_preorder_next_with_children_check!(get_value_and_children, Node::OwnedValue); +} + +impl<'a, Node> Iterator for OwnedBinaryLeavesIterator + where Node: OwnedBinaryTreeNode { + + type Item = Node::OwnedValue; + fn next(&mut self) -> Option { + loop { + let value = self.dfs_preorder_next(); + match value { + None => return None, + Some(value) => { + if value.0 { continue; } + return Some(value.1); + } + } + } + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 94d8f54..085dcb3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,4 +2,6 @@ pub mod prelude; mod bfs_iterators; mod dfs_preorder_iterators; mod dfs_inorder_iterators; -mod dfs_postorder_iterators; \ No newline at end of file +mod dfs_postorder_iterators; +mod make_peekable_iterator; +mod leaves_iterators; \ No newline at end of file diff --git a/src/make_peekable_iterator.rs b/src/make_peekable_iterator.rs new file mode 100644 index 0000000..f1f3773 --- /dev/null +++ b/src/make_peekable_iterator.rs @@ -0,0 +1,40 @@ +pub (crate) struct MakePeekableIterator { + iter: T, + lookahead: Option, +} + +impl MakePeekableIterator + where T: Iterator { + + pub (crate) fn new(iter: T) -> Self { + Self { + iter, + lookahead: None, + } + } + + pub (crate) fn peek(&mut self) -> Option<&T::Item> { + match &self.lookahead { + Some(_) => self.lookahead.as_ref(), + None => { + self.lookahead = self.iter.next(); + self.lookahead.as_ref() + } + } + } +} + +impl Iterator for MakePeekableIterator + where T: Iterator { + + type Item = T::Item; + + fn next(&mut self) -> Option { + match std::mem::take(&mut self.lookahead) { + Some(lookahead) => Some(lookahead), + None => { + self.iter.next() + } + } + } +} \ No newline at end of file diff --git a/src/prelude.rs b/src/prelude.rs index be3f141..3ca12cd 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -3,6 +3,19 @@ use std::iter::FlatMap; use std::slice::{Iter, IterMut}; use std::vec::IntoIter; +use super::leaves_iterators::owned::{ + OwnedLeavesIterator, + OwnedBinaryLeavesIterator +}; +use super::leaves_iterators::mut_borrow::{ + MutBorrowedLeavesIterator, + MutBorrowedBinaryLeavesIterator +}; +use super::leaves_iterators::borrow::{ + BorrowedLeavesIterator, + BorrowedBinaryLeavesIterator +}; + use super::bfs_iterators::{ owned::{ OwnedBFSIterator, @@ -211,7 +224,7 @@ pub trait OwnedBinaryTreeNode OwnedDFSInorderIterator::new(self) } - /// This method retrieves an iterable that can be used to perform + /// This method retrieves an iterator that can be used to perform /// Depth First Postorder searches of a tree. /// /// A Depth First Postorder search (referred to as DFS Postorder) @@ -246,6 +259,10 @@ pub trait OwnedBinaryTreeNode fn dfs_postorder(self) -> OwnedBinaryDFSPostorderIterator { OwnedBinaryDFSPostorderIterator::new(self) } + + fn leaves(self) -> OwnedBinaryLeavesIterator { + OwnedBinaryLeavesIterator::new(self) + } } /// A tree node where getting its children consumes its value. @@ -329,7 +346,7 @@ pub trait OwnedTreeNode OwnedDFSPreorderIterator::new(self) } - /// This method retrieves an iterable that can be used to perform + /// This method retrieves an iterator that can be used to perform /// Depth First Postorder searches of a tree. /// /// A Depth First Postorder search (referred to as DFS Postorder) @@ -364,6 +381,10 @@ pub trait OwnedTreeNode fn dfs_postorder(self) -> OwnedDFSPostorderIterator { OwnedDFSPostorderIterator::new(self) } + + fn leaves(self) -> OwnedLeavesIterator { + OwnedLeavesIterator::new(self) + } } /// A binary tree node where getting its children mutably borrows its value. @@ -490,7 +511,7 @@ pub trait MutBorrowedBinaryTreeNode<'a> MutBorrowedDFSInorderIterator::new(self) } - /// This method retrieves an iterable that can be used to perform + /// This method retrieves an iterator that can be used to perform /// Depth First Postorder searches of a tree. /// /// A Depth First Postorder search (referred to as DFS Postorder) @@ -525,6 +546,10 @@ pub trait MutBorrowedBinaryTreeNode<'a> fn dfs_postorder_iter_mut(&'a mut self) -> MutBorrowedBinaryDFSPostorderIterator<'a, Self> { MutBorrowedBinaryDFSPostorderIterator::new(self) } + + fn leaves_iter_mut(&'a mut self) -> MutBorrowedBinaryLeavesIterator<'a, Self> { + MutBorrowedBinaryLeavesIterator::new(self) + } } /// A tree node where getting its children mutably borrows its value. @@ -610,7 +635,7 @@ pub trait MutBorrowedTreeNode<'a> MutBorrowedDFSPreorderIterator::new(self) } - /// This method retrieves an iterable that can be used to perform + /// This method retrieves an iterator that can be used to perform /// Depth First Postorder searches of a tree. /// /// A Depth First Postorder search (referred to as DFS Postorder) @@ -645,6 +670,10 @@ pub trait MutBorrowedTreeNode<'a> fn dfs_postorder_iter_mut(&'a mut self) -> MutBorrowedDFSPostorderIterator<'a, Self> { MutBorrowedDFSPostorderIterator::new(self) } + + fn leaves_iter_mut(&'a mut self) -> MutBorrowedLeavesIterator<'a, Self> { + MutBorrowedLeavesIterator::new(self) + } } /// A binary tree node where getting its children borrows its value. @@ -771,7 +800,7 @@ pub trait BorrowedBinaryTreeNode<'a> BorrowedDFSInorderIterator::new(self) } - /// This method retrieves an iterable that can be used to perform + /// This method retrieves an iterator that can be used to perform /// Depth First Postorder searches of a tree. /// /// A Depth First Postorder search (referred to as DFS Postorder) @@ -806,6 +835,10 @@ pub trait BorrowedBinaryTreeNode<'a> fn dfs_postorder_iter(&'a self) -> BorrowedBinaryDFSPostorderIterator<'a, Self> { BorrowedBinaryDFSPostorderIterator::new(self) } + + fn leaves_iter(&'a self) -> BorrowedBinaryLeavesIterator<'a, Self> { + BorrowedBinaryLeavesIterator::new(self) + } } /// A tree node where getting its children borrows its value. @@ -890,7 +923,7 @@ pub trait BorrowedTreeNode<'a> BorrowedDFSPreorderIterator::new(self) } - /// This method retrieves an iterable that can be used to perform + /// This method retrieves an iterator that can be used to perform /// Depth First Postorder searches of a tree. /// /// A Depth First Postorder search (referred to as DFS Postorder) @@ -925,6 +958,10 @@ pub trait BorrowedTreeNode<'a> fn dfs_postorder_iter(&'a self) -> BorrowedDFSPostorderIterator<'a, Self> { BorrowedDFSPostorderIterator::new(self) } + + fn leaves_iter(&'a self) -> BorrowedLeavesIterator<'a, Self> { + BorrowedLeavesIterator::new(self) + } } impl OwnedTreeNode for TreeNode { @@ -1575,6 +1612,61 @@ pub (crate) mod tests { } } + mod leaves_tests { + use crate::prelude::*; + use super::{ + assert_len, + create_trees_for_testing, + create_binary_tree_for_testing, + }; + + fn get_expected_order_leaves() -> [usize; 4] { + [3,4,5,10] + } + + #[test] + fn leaves_have_correct_order() { + let expected = get_expected_order_leaves(); + for mut test_tree in create_trees_for_testing() { + for (i, value) in test_tree.leaves_iter().enumerate() { + assert_eq!(expected[i], *value); + } + assert_len!(expected.len(), test_tree.leaves_iter()); + + for (i, value) in test_tree.leaves_iter_mut().enumerate() { + assert_eq!(expected[i], *value); + } + assert_len!(expected.len(), test_tree.leaves_iter_mut()); + + for (i, value) in test_tree.clone().leaves().enumerate() { + assert_eq!(expected[i], value); + } + assert_len!(expected.len(), test_tree.leaves()); + } + } + + #[test] + fn binary_leaves_has_correct_order() { + let expected = get_expected_order_leaves(); + let mut test_tree = create_binary_tree_for_testing(); + + for (i, value) in test_tree.leaves_iter().enumerate() { + assert_eq!(expected[i], *value); + } + assert_len!(expected.len(), test_tree.leaves_iter()); + + for (i, value) in test_tree.leaves_iter_mut().enumerate() { + assert_eq!(expected[i], *value); + } + assert_len!(expected.len(), test_tree.leaves_iter_mut()); + + for (i, value) in test_tree.clone().leaves().enumerate() { + assert_eq!(expected[i], value); + } + assert_len!(expected.len(), test_tree.leaves()); + } + } + macro_rules! assert_len { ($expected: expr, $iter: expr) => { let mut count = 0;