From 94a03c78636d64ba97f5e6fe1b0ff17ed0fab1fb Mon Sep 17 00:00:00 2001 From: sgoudham Date: Wed, 16 Feb 2022 01:30:53 +0000 Subject: [PATCH] Implement (partial) BST --- Cargo.toml | 8 ++ src/ds.rs | 326 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 335 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/ds.rs create mode 100644 src/lib.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..18542c4 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "rust-commons" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/ds.rs b/src/ds.rs new file mode 100644 index 0000000..de11e58 --- /dev/null +++ b/src/ds.rs @@ -0,0 +1,326 @@ +use std::cmp::Ordering; +use std::collections::VecDeque; + +type Child = Option>>; + +pub struct IntoPreOrderIter(T); +pub struct IntoInOrderIter(T); +pub struct IntoPostOrderIter(T); + +#[derive(Debug)] +pub struct BST { + root: Child, +} + +#[derive(Debug)] +struct Node { + value: T, + left: Child, + right: Child, +} + +impl Node { + fn new(value: T) -> Node { + Node { + value, + left: None, + right: None, + } + } + + fn insert(&mut self, value: T) { + match value.cmp(&self.value) { + Ordering::Equal => {} + Ordering::Less => match self.left { + None => self.left = Some(Box::from(Node::new(value))), + Some(ref mut node) => node.insert(value), + }, + Ordering::Greater => match self.right { + None => self.right = Some(Box::from(Node::new(value))), + Some(ref mut node) => node.insert(value), + }, + } + } + + fn has_element(&self, value: T) -> bool { + match value.cmp(&self.value) { + Ordering::Equal => true, + Ordering::Less => match self.left { + None => false, + Some(ref node) => node.has_element(value), + }, + Ordering::Greater => match self.right { + None => false, + Some(ref node) => node.has_element(value), + }, + } + } + + fn retrieve(&self, value: T) -> Option<&T> { + match value.cmp(&self.value) { + Ordering::Equal => Some(&self.value), + Ordering::Less => match self.left { + None => None, + Some(ref node) => node.retrieve(value), + }, + Ordering::Greater => match self.right { + None => None, + Some(ref node) => node.retrieve(value), + }, + } + } + + fn retrieve_as_mut(&mut self, value: T) -> Option<&mut T> { + match value.cmp(&self.value) { + Ordering::Equal => Some(&mut self.value), + Ordering::Less => match self.left { + None => None, + Some(ref mut node) => node.retrieve_as_mut(value), + }, + Ordering::Greater => match self.right { + None => None, + Some(ref mut node) => node.retrieve_as_mut(value), + }, + } + } + + fn pre_order_traversal(node: Child, pre_order: &mut VecDeque) { + if let Some(node) = node { + pre_order.push_front(node.value); + Self::pre_order_traversal(node.left, pre_order); + Self::pre_order_traversal(node.right, pre_order); + } + } + + fn in_order_traversal(node: Child, in_order: &mut VecDeque) { + if let Some(node) = node { + Self::in_order_traversal(node.left, in_order); + in_order.push_front(node.value); + Self::in_order_traversal(node.right, in_order); + } + } + + fn post_order_traversal(node: Child, post_order: &mut VecDeque) { + if let Some(node) = node { + Self::post_order_traversal(node.left, post_order); + Self::post_order_traversal(node.right, post_order); + post_order.push_front(node.value); + } + } +} + +impl BST { + pub fn empty() -> Self { + Self { root: None } + } + + pub fn new(value: T) -> Self { + Self { + root: Some(Box::from(Node::new(value))), + } + } + + pub fn insert(&mut self, value: T) { + match self.root { + None => self.root = Some(Box::from(Node::new(value))), + Some(ref mut node) => node.insert(value), + } + } + + pub fn has_element(&self, value: T) -> bool { + match self.root { + None => false, + Some(ref node) => node.has_element(value), + } + } + + pub fn retrieve(&self, value: T) -> Option<&T> { + match self.root { + None => None, + Some(ref node) => node.retrieve(value), + } + } + + pub fn retrieve_as_mut(&mut self, value: T) -> Option<&mut T> { + match self.root { + None => None, + Some(ref mut node) => node.retrieve_as_mut(value), + } + } + + pub fn into_pre_order_iter(self) -> IntoPreOrderIter> { + let mut pre_order = VecDeque::new(); + Node::pre_order_traversal(self.root, &mut pre_order); + IntoPreOrderIter(pre_order) + } + + pub fn into_in_order_iter(self) -> IntoInOrderIter> { + let mut in_order = VecDeque::new(); + Node::in_order_traversal(self.root, &mut in_order); + IntoInOrderIter(in_order) + } + + pub fn into_post_order_iter(self) -> IntoPostOrderIter> { + let mut post_order = VecDeque::new(); + Node::post_order_traversal(self.root, &mut post_order); + IntoPostOrderIter(post_order) + } +} + +impl Iterator for IntoPreOrderIter> { + type Item = T; + + fn next(&mut self) -> Option { + self.0.pop_back() + } +} + +impl Iterator for IntoInOrderIter> { + type Item = T; + + fn next(&mut self) -> Option { + self.0.pop_back() + } +} + +impl Iterator for IntoPostOrderIter> { + type Item = T; + + fn next(&mut self) -> Option { + self.0.pop_back() + } +} + +// impl Drop for BST { +// fn drop(&mut self) { +// todo!("I need help with this :sob: :sob:") +// +// // let mut stack = vec![&self.root]; +// // let mut out: Vec<&LinkNode> = Vec::new(); +// // +// // while !stack.is_empty() { +// // let cur_node = stack.pop().unwrap(); +// // out.push(cur_node); +// // +// // if let Some(node) = &cur_node.as_ref().unwrap().left { +// // stack.push() +// // } +// // } +// } +// } + +#[cfg(test)] +mod bst_test { + use super::BST; + + #[test] + fn can_insert_element() { + let mut bst = BST::new(-1); + + bst.insert(0); + bst.insert(1); + bst.insert(1); + bst.insert(2); + + assert_eq!(bst.retrieve(-1), Some(&-1)); + assert_eq!(bst.retrieve(0), Some(&0)); + assert_eq!(bst.retrieve(1), Some(&1)); + assert_eq!(bst.retrieve(2), Some(&2)); + } + + #[test] + fn check_element_exists() { + let mut bst = BST::empty(); + + bst.insert(1); + bst.insert(5); + + assert!(bst.has_element(1)); + assert!(bst.has_element(5)); + assert!(!bst.has_element(10)); + } + + #[test] + fn retrieve_element_from_bst() { + let mut bst = BST::empty(); + bst.insert(5); + bst.insert(10); + + let retrieved_value = bst.retrieve(5); + let invalid_value = bst.retrieve(15); + + assert_eq!(retrieved_value, Some(&5)); + assert_eq!(invalid_value, None); + } + + #[test] + fn retrieve_element_as_mut_and_modify_bst() { + let mut bst = BST::empty(); + bst.insert(10); + bst.insert(5); + + let _retrieved_value_as_mut: &mut i32 = bst.retrieve_as_mut(5).unwrap(); + *_retrieved_value_as_mut = 2; + + assert!(bst.has_element(10)); + assert!(bst.has_element(2)); + assert!(!bst.has_element(5)); + } + + #[test] + fn pre_order_traversal() { + let mut bst = BST::empty(); + bst.insert(3); + bst.insert(4); + bst.insert(5); + bst.insert(1); + bst.insert(2); + + let mut pre_order_iter = bst.into_pre_order_iter(); + + assert_eq!(pre_order_iter.next(), Some(3)); + assert_eq!(pre_order_iter.next(), Some(1)); + assert_eq!(pre_order_iter.next(), Some(2)); + assert_eq!(pre_order_iter.next(), Some(4)); + assert_eq!(pre_order_iter.next(), Some(5)); + assert_eq!(pre_order_iter.next(), None); + } + + #[test] + fn in_order_traversal() { + let mut bst = BST::empty(); + bst.insert(3); + bst.insert(4); + bst.insert(5); + bst.insert(1); + bst.insert(2); + + let mut in_order_iter = bst.into_in_order_iter(); + + assert_eq!(in_order_iter.next(), Some(1)); + assert_eq!(in_order_iter.next(), Some(2)); + assert_eq!(in_order_iter.next(), Some(3)); + assert_eq!(in_order_iter.next(), Some(4)); + assert_eq!(in_order_iter.next(), Some(5)); + assert_eq!(in_order_iter.next(), None); + } + + #[test] + fn post_order_traversal() { + let mut bst = BST::empty(); + bst.insert(3); + bst.insert(4); + bst.insert(5); + bst.insert(1); + bst.insert(2); + + let mut post_order_traversal = bst.into_post_order_iter(); + + assert_eq!(post_order_traversal.next(), Some(2)); + assert_eq!(post_order_traversal.next(), Some(1)); + assert_eq!(post_order_traversal.next(), Some(5)); + assert_eq!(post_order_traversal.next(), Some(4)); + assert_eq!(post_order_traversal.next(), Some(3)); + assert_eq!(post_order_traversal.next(), None); + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..680426e --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +pub mod ds; \ No newline at end of file