Skip to content

Commit

Permalink
Implement leaves iterators - documentation needed!
Browse files Browse the repository at this point in the history
  • Loading branch information
mr-adult committed Oct 19, 2023
1 parent ea81557 commit b478116
Show file tree
Hide file tree
Showing 7 changed files with 452 additions and 7 deletions.
81 changes: 81 additions & 0 deletions src/leaves_iterators/borrow.rs
Original file line number Diff line number Diff line change
@@ -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<MakePeekableIterator<Node::BorrowedChildren>>,

}

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<Self::Item> {
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<MakePeekableIterator<BinaryChildren<&'a Node>>>,
}

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<Self::Item> {
loop {
let value = self.dfs_preorder_next();
match value {
None => return None,
Some(value) => {
if value.0 { continue; }
return Some(value.1);
}
}
}
}
}
70 changes: 70 additions & 0 deletions src/leaves_iterators/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
80 changes: 80 additions & 0 deletions src/leaves_iterators/mut_borrow.rs
Original file line number Diff line number Diff line change
@@ -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<MakePeekableIterator<Node::MutBorrowedChildren>>,
}

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<Self::Item> {
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<MakePeekableIterator<BinaryChildren<&'a mut Node>>>,
}

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<Self::Item> {
loop {
let value = self.dfs_preorder_next();
match value {
None => return None,
Some(value) => {
if value.0 { continue; }
return Some(value.1);
}
}
}
}
}
80 changes: 80 additions & 0 deletions src/leaves_iterators/owned.rs
Original file line number Diff line number Diff line change
@@ -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<Node>
where Node: OwnedTreeNode {

root: Option<Node>,
traversal_stack: Vec<MakePeekableIterator<Node::OwnedChildren>>,
}

impl<'a, Node> OwnedLeavesIterator<Node>
where Node: OwnedTreeNode {

pub (crate) fn new(root: Node) -> OwnedLeavesIterator<Node> {
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<Node>
where Node: OwnedTreeNode {

type Item = Node::OwnedValue;
fn next(&mut self) -> Option<Self::Item> {
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<Node>
where Node: OwnedBinaryTreeNode {

root: Option<Node>,
traversal_stack: Vec<MakePeekableIterator<BinaryChildren<Node>>>,
}

impl<'a, Node> OwnedBinaryLeavesIterator<Node>
where Node: OwnedBinaryTreeNode {

pub (crate) fn new(root: Node) -> OwnedBinaryLeavesIterator<Node> {
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<Node>
where Node: OwnedBinaryTreeNode {

type Item = Node::OwnedValue;
fn next(&mut self) -> Option<Self::Item> {
loop {
let value = self.dfs_preorder_next();
match value {
None => return None,
Some(value) => {
if value.0 { continue; }
return Some(value.1);
}
}
}
}
}
4 changes: 3 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ pub mod prelude;
mod bfs_iterators;
mod dfs_preorder_iterators;
mod dfs_inorder_iterators;
mod dfs_postorder_iterators;
mod dfs_postorder_iterators;
mod make_peekable_iterator;
mod leaves_iterators;
40 changes: 40 additions & 0 deletions src/make_peekable_iterator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
pub (crate) struct MakePeekableIterator<T: Iterator> {
iter: T,
lookahead: Option<T::Item>,
}

impl<T> MakePeekableIterator<T>
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<T> Iterator for MakePeekableIterator<T>
where T: Iterator {

type Item = T::Item;

fn next(&mut self) -> Option<Self::Item> {
match std::mem::take(&mut self.lookahead) {
Some(lookahead) => Some(lookahead),
None => {
self.iter.next()
}
}
}
}
Loading

0 comments on commit b478116

Please sign in to comment.