use std::cmp::Ordering::*; #[derive(Debug)] pub struct BinarySearchTree { root: Option>>, } #[derive(Debug)] struct Node { data: T, left: Option>>, right: Option>>, } impl BinarySearchTree { pub fn new() -> BinarySearchTree { BinarySearchTree { root: None } } pub fn insert(&mut self, data: T) { match self.root.take() { None => { self.root = Some(Box::new(Node { data, left: None, right: None, })) } Some(mut root) => { root.insert_child(data); self.root = Some(root); } } } pub fn find(&self, data: T) -> Option { self.root.as_ref().map(|root| root.find(data))? } } impl Node { fn new(data: T) -> Self { Node { data, left: None, right: None, } } fn insert_child(&mut self, data: T) { match self.data.cmp(&data) { Less => match self.right.take() { None => self.right = Some(Box::new(Node::new(data))), Some(mut right) => { right.insert_child(data); self.right = Some(right); } }, Equal | Greater => match self.left.take() { None => self.left = Some(Box::new(Node::new(data))), Some(mut left) => { left.insert_child(data); self.left = Some(left); } }, } } fn find(&self, data: T) -> Option { match self.data.cmp(&data) { Less => self.right.as_ref().map(|right| right.find(data))?, Equal => Some(data), Greater => self.left.as_ref().map(|left| left.find(data))?, } } } #[cfg(test)] mod tests { use super::*; #[test] fn insert_and_find() { let mut tree = BinarySearchTree::new(); tree.insert(1); assert_eq!(tree.find(1), Some(1)); } #[test] fn insert_three_values_find_third() { let mut tree = BinarySearchTree::new(); for num in [1, 2, 3] { tree.insert(num); } assert_eq!(tree.find(3), Some(3)); } #[test] fn multiple_finds() { let mut tree = BinarySearchTree::new(); for num in [1, 2, 3] { tree.insert(num); } for num in [1, 2, 3] { assert_eq!(tree.find(num), Some(num)); } } }