13.8 Creating Iterators for Complex Data Structures
Complex data structures (like trees or graphs) may need custom traversal. Rust’s iterator traits accommodate these scenarios just as well.
13.8.1 An In-Order Binary Tree Iterator
Tree Definition:
#![allow(unused)] fn main() { use std::cell::RefCell; use std::rc::Rc; #[derive(Debug)] struct TreeNode { value: i32, left: Option<Rc<RefCell<TreeNode>>>, right: Option<Rc<RefCell<TreeNode>>>, } impl TreeNode { fn new(value: i32) -> Rc<RefCell<Self>> { Rc::new(RefCell::new(TreeNode { value, left: None, right: None, })) } } }
In-Order Iterator:
#![allow(unused)] fn main() { struct InOrderIter { stack: Vec<Rc<RefCell<TreeNode>>>, current: Option<Rc<RefCell<TreeNode>>>, } impl InOrderIter { fn new(root: Rc<RefCell<TreeNode>>) -> Self { InOrderIter { stack: Vec::new(), current: Some(root), } } } impl Iterator for InOrderIter { type Item = i32; fn next(&mut self) -> Option<Self::Item> { while let Some(node) = self.current.clone() { self.stack.push(node.clone()); self.current = node.borrow().left.clone(); } if let Some(node) = self.stack.pop() { let value = node.borrow().value; self.current = node.borrow().right.clone(); Some(value) } else { None } } } }
Using the Iterator:
use std::rc::Rc; use std::cell::RefCell; #[derive(Debug)] struct TreeNode { value: i32, left: Option<Rc<RefCell<TreeNode>>>, right: Option<Rc<RefCell<TreeNode>>>, } impl TreeNode { fn new(value: i32) -> Rc<RefCell<Self>> { Rc::new(RefCell::new(TreeNode { value, left: None, right: None, })) } } struct InOrderIter { stack: Vec<Rc<RefCell<TreeNode>>>, current: Option<Rc<RefCell<TreeNode>>>, } impl InOrderIter { fn new(root: Rc<RefCell<TreeNode>>) -> Self { InOrderIter { stack: Vec::new(), current: Some(root), } } } impl Iterator for InOrderIter { type Item = i32; fn next(&mut self) -> Option<Self::Item> { while let Some(node) = self.current.clone() { self.stack.push(node.clone()); self.current = node.borrow().left.clone(); } if let Some(node) = self.stack.pop() { let value = node.borrow().value; self.current = node.borrow().right.clone(); Some(value) } else { None } } } fn main() { // Build a simple binary tree let root = TreeNode::new(4); let left = TreeNode::new(2); let right = TreeNode::new(6); root.borrow_mut().left = Some(left.clone()); root.borrow_mut().right = Some(right.clone()); left.borrow_mut().left = Some(TreeNode::new(1)); left.borrow_mut().right = Some(TreeNode::new(3)); right.borrow_mut().left = Some(TreeNode::new(5)); right.borrow_mut().right = Some(TreeNode::new(7)); // Traverse with InOrderIter let iter = InOrderIter::new(root.clone()); let traversal: Vec<i32> = iter.collect(); println!("{:?}", traversal); // [1, 2, 3, 4, 5, 6, 7] }