Skip to content

Commit

Permalink
feat(docs): document AVL trees (#89)
Browse files Browse the repository at this point in the history
  • Loading branch information
scriptandcompile authored Jun 17, 2024
1 parent ee8695a commit 308803e
Showing 1 changed file with 167 additions and 40 deletions.
207 changes: 167 additions & 40 deletions src/data_structures/avl_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,25 @@ struct AVLNode<T: Ord> {
right: Option<Box<AVLNode<T>>>,
}

/// A set based on an AVL Tree.
/// An AVL tree.
///
/// An AVL Tree is a self-balancing binary search tree. It tracks the height of each node
/// and performs internal rotations to maintain a height difference of at most 1 between
/// each sibling pair.
/// An AVL tree is a self-balancing binary search tree where the height difference between the left
/// and right subtrees of each node is at most 1. This guarantees a logarithmic height and
/// efficient operations.
///
/// # Examples
///
/// ```rust
/// use rust_algorithms::data_structures::AVLTree;
///
/// let mut tree = AVLTree::new();
/// tree.insert(1);
/// tree.insert(2);
///
/// assert!(tree.contains(&1));
/// assert!(tree.contains(&2));
/// assert!(!tree.contains(&3));
/// ```
pub struct AVLTree<T: Ord> {
root: Option<Box<AVLNode<T>>>,
length: usize,
Expand All @@ -32,14 +46,46 @@ enum Side {

impl<T: Ord> AVLTree<T> {
/// Creates an empty `AVLTree`.
///
/// # Examples
///
/// ```rust
/// use rust_algorithms::data_structures::AVLTree;
///
/// let tree: AVLTree<i32> = AVLTree::new();
///
/// assert!(tree.is_empty());
/// ```
pub fn new() -> AVLTree<T> {
AVLTree {
root: None,
length: 0,
}
}

/// Returns `true` if the tree contains a value.
/// Checks if the tree contains a value.
///
/// # Arguments
///
/// * `value`: A reference to the value to check for.
///
/// # Returns
///
/// `true` if the tree contains the value, `false` otherwise.
///
/// # Examples
///
/// ```rust
/// use rust_algorithms::data_structures::AVLTree;
///
/// let mut tree = AVLTree::new();
/// tree.insert(1);
///
/// // The tree should contain the value 1.
/// assert!(tree.contains(&1));
/// // The tree should not contain the value 2.
/// assert!(!tree.contains(&2));
/// ```
pub fn contains(&self, value: &T) -> bool {
let mut current = &self.root;
while let Some(node) = current {
Expand All @@ -54,7 +100,22 @@ impl<T: Ord> AVLTree<T> {

/// Adds a value to the tree.
///
/// Returns `true` if the tree did not yet contain the value.
/// # Returns
///
/// `true` if the tree did not yet contain the value, `false` otherwise.
///
/// # Examples
///
/// ```rust
/// use rust_algorithms::data_structures::AVLTree;
///
/// let mut tree = AVLTree::new();
///
/// // The first insertion should succeed.
/// assert!(tree.insert(1));
/// // The second insertion should fail, since the value is already in the tree.
/// assert!(!tree.insert(1));
/// ```
pub fn insert(&mut self, value: T) -> bool {
let inserted = insert(&mut self.root, value);
if inserted {
Expand All @@ -65,7 +126,23 @@ impl<T: Ord> AVLTree<T> {

/// Removes a value from the tree.
///
/// Returns `true` if the tree contained the value.
/// # Returns
///
/// `true` if the tree contained the value, `false` otherwise.
///
/// # Examples
///
/// ```rust
/// use rust_algorithms::data_structures::AVLTree;
///
/// let mut tree = AVLTree::new();
/// tree.insert(1);
///
/// // First removal should succeed, since the value is in the tree.
/// assert!(tree.remove(&1));
/// // The second removal should fail, since the value is no longer in the tree.
/// assert!(!tree.remove(&1));
/// ```
pub fn remove(&mut self, value: &T) -> bool {
let removed = remove(&mut self.root, value);
if removed {
Expand All @@ -75,11 +152,39 @@ impl<T: Ord> AVLTree<T> {
}

/// Returns the number of values in the tree.
///
/// # Returns
///
/// The number of values in the tree.
///
/// # Examples
///
/// ```rust
/// use rust_algorithms::data_structures::AVLTree;
///
/// let tree: AVLTree<_> = (1..4).collect();
///
/// assert_eq!(tree.len(), 3);
/// ```
pub fn len(&self) -> usize {
self.length
}

/// Returns `true` if the tree contains no values.
/// Detects if the AVL Tree is empty.
///
/// # Returns
///
/// `true` if the tree contains no values, `false` otherwise.
///
/// # Examples
///
/// ```rust
/// use rust_algorithms::data_structures::AVLTree;
///
/// let tree: AVLTree<i32> = AVLTree::new();
///
/// assert!(tree.is_empty());
/// ```
pub fn is_empty(&self) -> bool {
self.length == 0
}
Expand All @@ -99,7 +204,21 @@ impl<T: Ord> AVLTree<T> {
node_iter
}

/// Returns an iterator that visits the values in the tree in ascending order.
/// Gets an iterator that visits the values in the tree in ascending order.
///
/// # Returns
///
/// An iterator that visits the values in the tree in ascending order.
///
/// # Examples
///
/// ```rust
/// use rust_algorithms::data_structures::AVLTree;
///
/// let tree: AVLTree<_> = (1..4).collect();
///
/// assert_eq!(tree.iter().collect::<Vec<_>>(), vec![&1, &2, &3]);
/// ```
pub fn iter(&self) -> Iter<T> {
Iter {
node_iter: self.node_iter(),
Expand Down Expand Up @@ -251,7 +370,21 @@ impl<T: Ord> AVLNode<T> {
}
}

/// Default implementation for `AVLTree`.
///
/// Creates an empty `AVLTree`.
impl<T: Ord> Default for AVLTree<T> {
/// Creates an empty `AVLTree`.
///
/// # Examples
///
/// ```rust
/// use rust_algorithms::data_structures::AVLTree;
///
/// let tree: AVLTree<i32> = Default::default();
///
/// assert!(tree.is_empty());
/// ```
fn default() -> Self {
Self::new()
}
Expand Down Expand Up @@ -285,6 +418,9 @@ struct NodeIter<'a, T: Ord> {
stack: Vec<&'a AVLNode<T>>,
}

/// An iterator over the nodes of an `AVLTree`.
///
/// This struct is created by the `node_iter` method of `AVLTree`.
impl<'a, T: Ord> Iterator for NodeIter<'a, T> {
type Item = &'a AVLNode<T>;

Expand All @@ -310,9 +446,31 @@ pub struct Iter<'a, T: Ord> {
node_iter: NodeIter<'a, T>,
}

/// An iterator over the items of an `AVLTree`.
///
/// This struct is created by the `iter` method of `AVLTree`.
impl<'a, T: Ord> Iterator for Iter<'a, T> {
type Item = &'a T;

/// Returns the next value in the tree.
///
/// # Returns
///
/// The next value in the tree, or `None` if there are no more values.
///
/// # Examples
///
/// ```rust
/// use rust_algorithms::data_structures::AVLTree;
///
/// let tree: AVLTree<_> = (1..4).collect();
/// let mut iter = tree.iter();
///
/// assert_eq!(iter.next(), Some(&1));
/// assert_eq!(iter.next(), Some(&2));
/// assert_eq!(iter.next(), Some(&3));
/// assert_eq!(iter.next(), None);
/// ```
fn next(&mut self) -> Option<&'a T> {
match self.node_iter.next() {
Some(node) => Some(&node.value),
Expand All @@ -331,37 +489,6 @@ mod tests {
.all(|n| (-1..=1).contains(&n.balance_factor()))
}

#[test]
fn len() {
let tree: AVLTree<_> = (1..4).collect();
assert_eq!(tree.len(), 3);
}

#[test]
fn contains() {
let tree: AVLTree<_> = (1..4).collect();
assert!(tree.contains(&1));
assert!(!tree.contains(&4));
}

#[test]
fn insert() {
let mut tree = AVLTree::new();
// First insert succeeds
assert!(tree.insert(1));
// Second insert fails
assert!(!tree.insert(1));
}

#[test]
fn remove() {
let mut tree: AVLTree<_> = (1..8).collect();
// First remove succeeds
assert!(tree.remove(&4));
// Second remove fails
assert!(!tree.remove(&4));
}

#[test]
fn sorted() {
let tree: AVLTree<_> = (1..8).rev().collect();
Expand Down

0 comments on commit 308803e

Please sign in to comment.