#[derive(Debug)]
pub struct BinomialTree<T: std::cmp::Ord> {
rank: usize,
children: Vec<Option<BinomialTree<T>>>,
payload: Option<T>,
min: bool,
}
impl<T: std::cmp::Ord> BinomialTree<T> {
pub fn init_min(payload: T) -> BinomialTree<T> {
BinomialTree::init(payload, true)
}
pub fn init_max(payload: T) -> BinomialTree<T> {
BinomialTree::init(payload, false)
}
pub fn init(payload: T, min: bool) -> BinomialTree<T> {
BinomialTree {
rank: 0,
children: Vec::new(),
payload: Some(payload),
min,
}
}
fn add(&mut self, binomial_tree: BinomialTree<T>) {
self.children.push(Some(binomial_tree));
self.rank += 1;
}
pub fn merge(
mut binomial_tree_1: BinomialTree<T>,
mut binomial_tree_2: BinomialTree<T>,
) -> BinomialTree<T> {
if binomial_tree_1.rank() != binomial_tree_2.rank {
panic!("Binomial tree ranks must be the same when merging");
}
if binomial_tree_1.is_min() != binomial_tree_2.is_min() {
panic!("Both binomial trees must be of the same type(both min or both max)");
}
let trees_are_min = binomial_tree_1.is_min();
let trees_are_max = binomial_tree_1.is_max();
if (trees_are_min && BinomialTree::is_smaller_or_equal(&binomial_tree_1, &binomial_tree_2))
|| (trees_are_max
&& BinomialTree::is_greater_or_equal(&binomial_tree_1, &binomial_tree_2))
{
binomial_tree_1.add(binomial_tree_2);
return binomial_tree_1;
} else {
binomial_tree_2.add(binomial_tree_1);
return binomial_tree_2;
}
}
pub fn rank(&self) -> usize {
self.rank
}
pub fn is_min(&self) -> bool {
self.min
}
pub fn is_max(&self) -> bool {
!self.is_min()
}
pub fn get_payload(&mut self) -> T {
if self.payload == None {
panic!("Payload is None");
}
self.payload.take().unwrap()
}
pub fn peek_payload(&self) -> &Option<T> {
&self.payload
}
pub fn is_smaller_or_equal(first: &BinomialTree<T>, other: &BinomialTree<T>) -> bool {
match (first.peek_payload(), other.peek_payload()) {
(Some(payload1), Some(payload2)) => payload1 <= payload2,
_ => panic!("Payloads can not be None"), }
}
pub fn is_greater_or_equal(first: &BinomialTree<T>, other: &BinomialTree<T>) -> bool {
match (first.peek_payload(), other.peek_payload()) {
(Some(payload1), Some(payload2)) => payload1 >= payload2,
_ => panic!("Payloads can not be None"), }
}
pub fn children_mut(&mut self) -> &mut Vec<Option<BinomialTree<T>>> {
&mut self.children
}
pub fn children(&self) -> &Vec<Option<BinomialTree<T>>> {
&self.children
}
}
impl<T: std::cmp::Ord + std::fmt::Display> BinomialTree<T> {
pub fn preorder(root: &BinomialTree<T>) -> String {
return String::from(BinomialTree::_pre_visit(&Some(root)).trim());
}
fn _pre_visit(node: &Option<&BinomialTree<T>>) -> String {
let mut node_list = String::from("");
match node {
None => node_list, Some(data) => {
match data.peek_payload() {
Some(value) => node_list.push_str(format!("{} ", value).as_str()), None => (), }
for i in 0..data.children.len() {
match &data.children[i] {
Some(data) => {
node_list.push_str(BinomialTree::_pre_visit(&Some(&data)).as_str())
}
None => (), }
}
node_list
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn tree_binomial_init_min() {
let bt = BinomialTree::init_min(0);
assert_eq!(*bt.peek_payload(), Some(0));
assert_eq!(bt.is_max(), false);
assert_eq!(bt.is_min(), true);
assert_eq!(bt.rank, 0);
assert_eq!(bt.children.len(), 0);
assert_eq!(BinomialTree::preorder(&bt), String::from("0"));
}
#[test]
fn tree_binomial_init_max() {
let bt = BinomialTree::init_max(0);
assert_eq!(*bt.peek_payload(), Some(0));
assert_eq!(bt.is_max(), true);
assert_eq!(bt.is_min(), false);
assert_eq!(bt.rank, 0);
assert_eq!(bt.children.len(), 0);
assert_eq!(BinomialTree::preorder(&bt), String::from("0"));
}
#[test]
fn tree_binomial_merge_rank_0_min() {
let bt1 = BinomialTree::init_min(0);
let bt2 = BinomialTree::init_min(1);
let merged_tree = BinomialTree::merge(bt1, bt2);
assert_eq!(BinomialTree::preorder(&merged_tree), String::from("0 1"));
assert_eq!(merged_tree.rank(), 1);
}
#[test]
fn tree_binomial_merge_rank_0_max() {
let bt1 = BinomialTree::init_max(0);
let bt2 = BinomialTree::init_max(1);
let merged_tree = BinomialTree::merge(bt1, bt2);
assert_eq!(BinomialTree::preorder(&merged_tree), String::from("1 0"));
assert_eq!(merged_tree.rank(), 1);
}
#[test]
fn tree_binomial_merge_rank_0_ref_min() {
let bt1 = BinomialTree::init_min(String::from("a"));
let bt2 = BinomialTree::init_min(String::from("b"));
let merged_tree = BinomialTree::merge(bt1, bt2);
assert_eq!(BinomialTree::preorder(&merged_tree), String::from("a b"));
assert_eq!(merged_tree.rank(), 1);
}
#[test]
fn tree_binomial_merge_rank_0_ref_max() {
let bt1 = BinomialTree::init_max(String::from("a"));
let bt2 = BinomialTree::init_max(String::from("b"));
let merged_tree = BinomialTree::merge(bt1, bt2);
assert_eq!(BinomialTree::preorder(&merged_tree), String::from("b a"));
assert_eq!(merged_tree.rank(), 1);
}
#[test]
fn tree_binomial_merge_rank_1_min() {
let bt1 = BinomialTree::init_min(0);
let bt2 = BinomialTree::init_min(1);
let merged_tree_1 = BinomialTree::merge(bt1, bt2);
let bt3 = BinomialTree::init_min(2);
let bt4 = BinomialTree::init_min(3);
let merged_tree_2 = BinomialTree::merge(bt3, bt4);
let merged_tree = BinomialTree::merge(merged_tree_1, merged_tree_2);
assert_eq!(
BinomialTree::preorder(&merged_tree),
String::from("0 1 2 3")
);
assert_eq!(merged_tree.rank(), 2);
}
#[test]
fn tree_binomial_merge_rank_1_max() {
let bt1 = BinomialTree::init_max(0);
let bt2 = BinomialTree::init_max(1);
let merged_tree_1 = BinomialTree::merge(bt1, bt2);
let bt3 = BinomialTree::init_max(2);
let bt4 = BinomialTree::init_max(3);
let merged_tree_2 = BinomialTree::merge(bt3, bt4);
let merged_tree = BinomialTree::merge(merged_tree_1, merged_tree_2);
assert_eq!(
BinomialTree::preorder(&merged_tree),
String::from("3 2 1 0")
);
assert_eq!(merged_tree.rank(), 2);
}
#[test]
fn tree_binomial_merge_rank_2_min() {
let bt1 = BinomialTree::init_min(0);
let bt2 = BinomialTree::init_min(1);
let merged_tree_1 = BinomialTree::merge(bt1, bt2);
let bt3 = BinomialTree::init_min(2);
let bt4 = BinomialTree::init_min(3);
let merged_tree_2 = BinomialTree::merge(bt3, bt4);
let merged_tree_final_1 = BinomialTree::merge(merged_tree_1, merged_tree_2);
let bt1 = BinomialTree::init_min(1);
let bt2 = BinomialTree::init_min(2);
let merged_tree_1 = BinomialTree::merge(bt1, bt2);
let bt3 = BinomialTree::init_min(5);
let bt4 = BinomialTree::init_min(6);
let merged_tree_2 = BinomialTree::merge(bt3, bt4);
let merged_tree_final_2 = BinomialTree::merge(merged_tree_1, merged_tree_2);
let merged_tree = BinomialTree::merge(merged_tree_final_1, merged_tree_final_2);
assert_eq!(
BinomialTree::preorder(&merged_tree),
String::from("0 1 2 3 1 2 5 6")
);
assert_eq!(merged_tree.rank(), 3);
}
#[test]
fn tree_binomial_merge_rank_2_max() {
let bt1 = BinomialTree::init_max(0);
let bt2 = BinomialTree::init_max(1);
let merged_tree_1 = BinomialTree::merge(bt1, bt2);
let bt3 = BinomialTree::init_max(2);
let bt4 = BinomialTree::init_max(3);
let merged_tree_2 = BinomialTree::merge(bt3, bt4);
let merged_tree_final_1 = BinomialTree::merge(merged_tree_1, merged_tree_2);
let bt1 = BinomialTree::init_max(1);
let bt2 = BinomialTree::init_max(2);
let merged_tree_1 = BinomialTree::merge(bt1, bt2);
let bt3 = BinomialTree::init_max(5);
let bt4 = BinomialTree::init_max(6);
let merged_tree_2 = BinomialTree::merge(bt3, bt4);
let merged_tree_final_2 = BinomialTree::merge(merged_tree_1, merged_tree_2);
let merged_tree = BinomialTree::merge(merged_tree_final_1, merged_tree_final_2);
assert_eq!(
BinomialTree::preorder(&merged_tree),
String::from("6 5 2 1 3 2 1 0")
);
assert_eq!(merged_tree.rank(), 3);
}
#[test]
#[should_panic(expected = "Both binomial trees must be of the same type(both min or both max)")]
fn tree_binomial_panic_merge_min_max() {
let min_bt = BinomialTree::init_min(0);
let max_bt = BinomialTree::init_max(0);
BinomialTree::merge(min_bt, max_bt);
}
#[test]
#[should_panic(expected = "Binomial tree ranks must be the same when merging")]
fn tree_binomial_panic_merge_different_ranks() {
let bt1 = BinomialTree::init_min(0);
let bt2 = BinomialTree::init_min(0);
let bt3 = BinomialTree::init_min(0);
let merged_tree = BinomialTree::merge(bt1, bt2);
BinomialTree::merge(bt3, merged_tree);
}
#[test]
#[should_panic(expected = "Payload is None")]
fn tree_binomial_panic_get_payload() {
let mut bt1 = BinomialTree::init_min(0);
bt1.get_payload();
bt1.get_payload();
}
}