170 lines
4.2 KiB
Rust
170 lines
4.2 KiB
Rust
//! An unbalanced binary tree type where each node has an optional left and right child.
|
|
//!
|
|
//! # Examples
|
|
//!
|
|
//! ```
|
|
//! use gemla::btree;
|
|
//!
|
|
//! // Tree with 2 nodes, one root node and one on the left side
|
|
//! let mut t = btree!(1, btree!(2),);
|
|
//!
|
|
//! assert_eq!(t.height(), 2);
|
|
//! assert_eq!(t.left.unwrap().val, 2);
|
|
//! assert_eq!(t.right, None);
|
|
//!
|
|
//! t.right = Some(Box::new(btree!(3)));
|
|
//! assert_eq!(t.right.unwrap().val, 3);
|
|
//! ```
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
use std::cmp::max;
|
|
|
|
/// An unbalanced binary tree type where each node has an optional left and right child.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// use gemla::btree;
|
|
///
|
|
/// // Tree with 2 nodes, one root node and one on the left side
|
|
/// let mut t = btree!(1, btree!(2),);
|
|
///
|
|
/// assert_eq!(t.height(), 2);
|
|
/// assert_eq!(t.left.unwrap().val, 2);
|
|
/// assert_eq!(t.right, None);
|
|
///
|
|
/// t.right = Some(Box::new(btree!(3)));
|
|
/// assert_eq!(t.right.unwrap().val, 3);
|
|
/// ```
|
|
#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Debug)]
|
|
pub struct Tree<T> {
|
|
pub val: T,
|
|
pub left: Option<Box<Tree<T>>>,
|
|
pub right: Option<Box<Tree<T>>>,
|
|
}
|
|
|
|
/// Short-hand for constructing Trees. `btree!` takes 3 arguments, the first being the
|
|
/// value of the root node, and the other two being child nodes. The last two arguments are
|
|
/// optional.
|
|
///
|
|
/// ```
|
|
/// use gemla::tree::*;
|
|
/// use gemla::btree;
|
|
///
|
|
/// # fn main() {
|
|
/// // A tree with two child nodes.
|
|
/// let t = btree!(1, btree!(2), btree!(3));
|
|
/// assert_eq!(t,
|
|
/// Tree::new(1,
|
|
/// Some(Box::new(Tree::new(2, None, None))),
|
|
/// Some(Box::new(Tree::new(3, None, None)))));
|
|
///
|
|
/// // A tree with only a left node.
|
|
/// let t_left = btree!(1, btree!(2),);
|
|
/// assert_eq!(t_left,
|
|
/// Tree::new(1,
|
|
/// Some(Box::new(Tree::new(2, None, None))),
|
|
/// None));
|
|
///
|
|
/// // A tree with only a right node.
|
|
/// let t_right = btree!(1, , btree!(3));
|
|
/// assert_eq!(t_right,
|
|
/// Tree::new(1,
|
|
/// None,
|
|
/// Some(Box::new(Tree::new(3, None, None)))));
|
|
///
|
|
/// // A tree with no child nodes.
|
|
/// let t_single = btree!(1);
|
|
/// assert_eq!(t_single,
|
|
/// Tree::new(1,
|
|
/// None,
|
|
/// None));
|
|
/// # }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! btree {
|
|
($val:expr, $l:expr, $r:expr) => {
|
|
$crate::tree::Tree::new($val, Some(Box::new($l)), Some(Box::new($r)))
|
|
};
|
|
($val:expr, , $r:expr) => {
|
|
$crate::tree::Tree::new($val, None, Some(Box::new($r)))
|
|
};
|
|
($val:expr, $l:expr,) => {
|
|
$crate::tree::Tree::new($val, Some(Box::new($l)), None)
|
|
};
|
|
($val:expr) => {
|
|
$crate::tree::Tree::new($val, None, None)
|
|
};
|
|
}
|
|
|
|
impl<T> Tree<T> {
|
|
/// Constructs a new [`Tree`] object
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// use gemla::tree::*;
|
|
///
|
|
/// let t = Tree::new(1, None, None);
|
|
/// assert_eq!(t, Tree {
|
|
/// val: 1,
|
|
/// left: None,
|
|
/// right: None
|
|
/// });
|
|
/// ```
|
|
pub fn new(val: T, left: Option<Box<Tree<T>>>, right: Option<Box<Tree<T>>>) -> Tree<T> {
|
|
Tree { val, left, right }
|
|
}
|
|
|
|
/// Obtains the height of the longest branch in a [`Tree`]
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// use gemla::tree::*;
|
|
/// use gemla::btree;
|
|
///
|
|
/// let t =
|
|
/// btree!("a",
|
|
/// btree!("aa",
|
|
/// btree!("aaa"),),
|
|
/// btree!("ab"));
|
|
/// assert_eq!(t.height(), 3);
|
|
/// ```
|
|
pub fn height(&self) -> usize {
|
|
match (self.left.as_ref(), self.right.as_ref()) {
|
|
(Some(l), Some(r)) => max(l.height(), r.height()) + 1,
|
|
(Some(l), None) => l.height() + 1,
|
|
(None, Some(r)) => r.height() + 1,
|
|
_ => 1,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_new() {
|
|
assert_eq!(
|
|
Tree::new(30, None, Some(Box::new(Tree::new(20, None, None)))),
|
|
Tree {
|
|
val: 30,
|
|
left: None,
|
|
right: Some(Box::new(Tree {
|
|
val: 20,
|
|
left: None,
|
|
right: None,
|
|
})),
|
|
}
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_height() {
|
|
assert_eq!(1, btree!(1).height());
|
|
|
|
assert_eq!(3, btree!(1, btree!(2), btree!(2, btree!(3),)).height());
|
|
}
|
|
}
|