diff --git a/tree/src/lib.rs b/tree/src/lib.rs index 4644876..337a97f 100644 --- a/tree/src/lib.rs +++ b/tree/src/lib.rs @@ -9,6 +9,10 @@ use std::{ rc::Rc, }; +// I need to take what I learned about linked lists and about the other Tree data structure, and +// apply it here with arena allocation. +// +// Also, smarter node allocation and pointer handling in order to avoid clones. #[derive(Clone, Debug, Default)] pub enum Tree { #[default] @@ -55,6 +59,16 @@ impl Tree { None } + // Do a depth-first-search in order to get the path to a node. Start with a naive recursive + // implementation, then switch to a stack-based implementation in order to avoid exceeding the + // stack. + pub fn path_to(&self, f: F) -> Vec> + where + F: FnOnce(&T) -> bool + Copy, + { + unimplemented!() + } + /// Convert each node of a tree from type T to type U pub fn map(&self, op: F) -> Tree where @@ -146,6 +160,13 @@ impl Node { } } +impl PartialEq for Node { + fn eq(&self, other: &Node) -> bool { + self.0.borrow().value == other.0.borrow().value + && self.0.borrow().children == other.0.borrow().children + } +} + #[cfg(test)] mod tests { use super::*; @@ -184,4 +205,31 @@ mod tests { assert!(tree2.find_bfs(|val| *val == "16").is_some()); assert!(tree2.find_bfs(|val| *val == "17").is_some()); } + + #[test] + fn path_to_on_empty_tree_returns_empty() { + let tree: Tree<&str> = Tree::default(); + + assert_eq!(tree.path_to(|val| *val == "i"), vec![]); + } + + // A + // B G H + // C I + // D E F + #[test] + fn it_can_find_a_path_to_a_node() { + let (tree, a) = Tree::new("A"); + let b = a.add_child_value("B"); + let c = b.add_child_value("C"); + let _d = c.add_child_value("D"); + let _e = c.add_child_value("D"); + let _f = c.add_child_value("D"); + let _g = a.add_child_value("G"); + let h = a.add_child_value("H"); + let i = a.add_child_value("I"); + + assert_eq!(tree.path_to(|val| *val == "z"), vec![]); + assert_eq!(tree.path_to(|val| *val == "i"), vec![a, h, i]); + } }