From 6ee6044168685e56a3724026fe977e43cd819c96 Mon Sep 17 00:00:00 2001 From: sgoudham Date: Tue, 22 Feb 2022 01:14:16 +0000 Subject: [PATCH] WIP add documentation --- src/lib.rs | 128 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 105 insertions(+), 23 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 39fee02..71a718c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,14 +9,14 @@ //! ## Author Notes //! //! I have made this library with the personal goals of learning and solidifying concepts such -//! as ownership, borrowing, generics and lifetimes. I cannot promise that the implementations are +//! as **ownership**, **borrowing**, **generics** and **lifetimes**. I cannot promise that the implementations are //! particularly efficient, or if they are, it was not at the forefront of my mind. //! -//! That being said, there are some areas I would love to improve/include: -//! - Write Rust more idiomatically. -//! - Implement a `pretty_print()` function to display the binary search trees nicely. -//! - Implementing the Drop trait for iterative node cleanup. -//! - Pre-allocating space on the heap for nodes to reduce inefficiency of inserts. +//! That being said, there are some areas I would love to improve upon/include: +//! - Write idiomatic code. +//! - Implement a **pretty_print()** function to display the binary search trees nicely. +//! - Implement [Drop] trait for iterative node cleanup. +//! - Pre-allocate space on the heap for nodes to reduce inefficiency of inserts. //! //! I'm more than happy to accept (and encourage) contributions if anyone is kind enough to do so. //! @@ -113,23 +113,20 @@ use std::vec::IntoIter; /// assert_eq!(bst_from_vec.in_order_vec(), vec![&2, &5, &10, &15, &18]); /// assert_eq!(bst_from_vec.sorted_vec(), vec![&2, &5, &10, &15, &18]); pub trait BinarySearchTree { - /// Create an empty Binary Search Tree - /// - /// No nodes are allocated on the heap yet - /// - /// # Examples - /// - /// ```rust - /// use bst_rs::{BinarySearchTree, IterativeBST}; - /// - /// let mut bst: IterativeBST = IterativeBST::new(); - /// assert!(bst.is_empty()) - fn new() -> Self; - + /// Returns the total **number of nodes** within the tree fn size(&self) -> usize; + + /// Returns `true` if the binary search tree contains no nodes fn is_empty(&self) -> bool; + + /// Returns `true` if the binary search tree contains one or more nodes fn is_not_empty(&self) -> bool; + + /// Inserts given `value` as an node into the binary search tree. + /// + /// Duplicate values are _not allowed_. fn insert(&mut self, value: T); + fn contains(&self, value: &T) -> bool; fn remove(&mut self, value: &T); fn retrieve(&self, value: &T) -> Option<&T>; @@ -157,12 +154,29 @@ pub trait BinarySearchTree { type HeapNode = Option>>; +/// A Recursive Binary Search Tree implementation, defined as `RecursiveBST` where T _must_ +/// implement trait [Ord]. +/// +/// # Important +/// +/// It is also important to note that [RecursiveBST] is more likely to **blow the stack** and is +/// generally less performant compared to [IterativeBST]. +/// +/// For more information on why that is the case, please have a look at +/// [The Story of Tail Call Optimizations in Rust.](https://seanchen1991.github.io/posts/tco-story/) #[derive(Debug)] pub struct RecursiveBST { root: HeapNode, size: usize, } +/// Am Iterative Binary Search Tree implementation, defined as `IterativeBST` where T _must_ +/// implement trait [Ord]. +/// +/// # Important +/// +/// This should be preferred against [RecursiveBST] as this should generally be +/// more performant. #[derive(Debug)] pub struct IterativeBST { root: HeapNode, @@ -296,14 +310,48 @@ impl Display for RecursiveBST { } } -impl BinarySearchTree for IterativeBST { - fn new() -> IterativeBST { +impl IterativeBST { + /// Creates an empty `IterativeBST` + /// + /// No nodes are allocated on the heap yet + /// + /// # Examples + /// + /// ```rust + /// use bst_rs::{BinarySearchTree, IterativeBST}; + /// + /// // Empty tree is created + /// let mut bst: IterativeBST = IterativeBST::new(); + /// assert!(bst.is_empty()) + pub fn new() -> IterativeBST { IterativeBST { root: None, size: 0, } } +} + +impl Default for IterativeBST { + /// Creates an empty `IterativeBST` + fn default() -> IterativeBST { + IterativeBST::new() + } +} +impl BinarySearchTree for IterativeBST { + /// Returns the total **number of nodes** within the tree. + /// + /// # Examples + /// + /// ```rust + /// use bst_rs::{BinarySearchTree, IterativeBST}; + /// + /// let mut bst = IterativeBST::new(); + /// bst.insert(5); + /// bst.insert(10); + /// bst.insert(3); + /// + /// assert_eq!(bst.size(), 3); fn size(&self) -> usize { self.size } @@ -428,14 +476,48 @@ impl BinarySearchTree for IterativeBST { } } -impl BinarySearchTree for RecursiveBST { - fn new() -> RecursiveBST { +impl RecursiveBST { + /// Creates an empty `RecursiveBST` + /// + /// No nodes are allocated on the heap yet + /// + /// # Examples + /// + /// ```rust + /// use bst_rs::{BinarySearchTree, RecursiveBST}; + //t / + /// // Empty tree is created + /// let mut bst: RecursiveBST = RecursiveBST::new(); + /// assert!(bst.is_empty()) + pub fn new() -> RecursiveBST { RecursiveBST { root: None, size: 0, } } +} + +impl Default for RecursiveBST { + /// Creates an empty `RecursiveBST` + fn default() -> RecursiveBST { + RecursiveBST::new() + } +} +impl BinarySearchTree for RecursiveBST { + /// Returns the total **number of nodes** within the tree. + /// + /// # Examples + /// + /// ```rust + /// use bst_rs::{BinarySearchTree, RecursiveBST}; + /// + /// let mut bst = RecursiveBST::new(); + /// bst.insert(5); + /// bst.insert(10); + /// bst.insert(3); + /// + /// assert_eq!(bst.size(), 3); fn size(&self) -> usize { self.size }