use crate::tree::BinomialTree;
#[derive(Debug)]
pub struct BinomialHeap<T: std::cmp::Ord> {
roots: Vec<Option<BinomialTree<T>>>,
candidate_root_index: usize,
size: usize,
min: bool,
}
impl<T: std::cmp::Ord> BinomialHeap<T> {
fn init(payload: T, min: bool) -> BinomialHeap<T> {
let root = Some(BinomialTree::init(payload, min));
let mut roots = Vec::new();
roots.push(root);
BinomialHeap {
roots: roots,
size: 1,
candidate_root_index: 0,
min,
}
}
pub fn init_min(payload: T) -> BinomialHeap<T> {
BinomialHeap::init(payload, true)
}
pub fn init_max(payload: T) -> BinomialHeap<T> {
BinomialHeap::init(payload, false)
}
pub fn merge(
binomial_heap_1: BinomialHeap<T>,
binomial_heap_2: BinomialHeap<T>,
) -> BinomialHeap<T> {
if binomial_heap_1.is_min() != binomial_heap_2.is_min() {
panic!("Both binomial heaps must be of the same type(both min or both max)");
}
if binomial_heap_1.max_tree_rank() <= binomial_heap_2.max_tree_rank() {
BinomialHeap::_merge(binomial_heap_1, binomial_heap_2)
} else {
BinomialHeap::_merge(binomial_heap_2, binomial_heap_1)
}
}
fn _merge(
mut binomial_heap_1: BinomialHeap<T>,
mut binomial_heap_2: BinomialHeap<T>,
) -> BinomialHeap<T> {
binomial_heap_2.set_size(binomial_heap_2.size() + binomial_heap_1.size());
for i in 0..binomial_heap_1.max_tree_rank() {
match binomial_heap_1.roots[i].take() {
Some(binomial_tree) => {
binomial_heap_2._push(binomial_tree);
}
None => (),
}
}
binomial_heap_2
}
pub fn push(&mut self, payload: T) {
let new_node = BinomialTree::init(payload, self.is_min());
self._push(new_node);
self.size += 1;
}
fn _push(&mut self, mut new_node: BinomialTree<T>) {
let max_rank = self.roots.len();
let start_rank = new_node.rank();
for i in start_rank..max_rank {
match self.roots[i].take() {
Some(node) => {
new_node = BinomialTree::merge(node, new_node);
if i == max_rank - 1 {
self.roots.push(Some(new_node));
break;
}
}
None => {
self.roots[i] = Some(new_node);
break;
}
}
}
self.candidate_root_index = self.find_candidate_root_index();
}
pub fn pop(&mut self) -> Option<T> {
if self.is_empty() {
return None;
}
let candidate_index = self.find_candidate_root_index();
let mut popped_node = self.roots[candidate_index].take().unwrap();
for i in 0..popped_node.children().len() {
let child = popped_node.children_mut()[i].take().unwrap();
self._push(child);
}
self.size -= 1;
Some(popped_node.get_payload())
}
pub fn peek(&self) -> &Option<T> {
if self.is_empty() {
return &None;
}
self.roots[self.candidate_root_index]
.as_ref()
.unwrap()
.peek_payload()
}
pub fn clear(&mut self) {
self.roots.clear();
self.size = 0;
}
pub fn size(&self) -> usize {
self.size
}
fn set_size(&mut self, size: usize) {
self.size = size;
}
pub fn is_min(&self) -> bool {
self.min
}
pub fn is_max(&self) -> bool {
!self.is_min()
}
pub fn is_empty(&self) -> bool {
self.size() == 0
}
fn max_tree_rank(&self) -> usize {
self.roots.len()
}
fn find_candidate_root_index(&self) -> usize {
let mut candidate_index = 0;
let mut candidate_node_option: &Option<BinomialTree<T>>;
for i in 0..self.roots.len() {
match &self.roots[i] {
Some(_) => {
candidate_index = i; break;
}
None => (),
}
}
candidate_node_option = &self.roots[candidate_index];
for i in candidate_index + 1..self.roots.len() {
match (&self.roots[i], candidate_node_option) {
(Some(node), Some(largest_priority_node)) => {
if (self.is_min()
&& BinomialTree::is_smaller_or_equal(&node, largest_priority_node))
|| (self.is_max()
&& BinomialTree::is_greater_or_equal(&node, largest_priority_node))
{
candidate_index = i; }
}
_ => (),
}
candidate_node_option = &self.roots[candidate_index]; }
candidate_index
}
}
impl<T: std::cmp::Ord + std::fmt::Display> BinomialHeap<T> {
pub fn preorder(binomial_heap: &BinomialHeap<T>) -> String {
let mut node_list = String::from("");
for i in 0..binomial_heap.roots.len() {
node_list.push_str(format!("Rank {}: ", i).as_str());
match &binomial_heap.roots[i] {
Some(binomial_tree) => {
node_list.push_str(BinomialTree::preorder(&binomial_tree).as_str())
}
None => (),
}
node_list.push_str("\n");
}
node_list
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn heap_binomial_init_min() {
let bh = BinomialHeap::init_min(0);
assert_eq!(BinomialHeap::preorder(&bh), format!("Rank 0: 0\n"));
assert_eq!(bh.is_min(), true);
assert_eq!(bh.is_max(), false);
}
#[test]
fn heap_binomial_init_max() {
let bh = BinomialHeap::init_max(0);
assert_eq!(BinomialHeap::preorder(&bh), format!("Rank 0: 0\n"));
assert_eq!(bh.is_min(), false);
assert_eq!(bh.is_max(), true);
}
#[test]
fn heap_binomial_push_min_1() {
let mut bh = BinomialHeap::init_min(0);
bh.push(1);
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: \nRank 1: 0 1\n")
);
}
#[test]
fn heap_binomial_push_max_1() {
let mut bh = BinomialHeap::init_max(0);
bh.push(1);
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: \nRank 1: 1 0\n")
);
}
#[test]
fn heap_binomial_push_min_2() {
let mut bh = BinomialHeap::init_min(0);
bh.push(1);
bh.push(2);
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: 2\nRank 1: 0 1\n")
);
}
#[test]
fn heap_binomial_push_max_2() {
let mut bh = BinomialHeap::init_max(0);
bh.push(1);
bh.push(2);
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: 2\nRank 1: 1 0\n")
);
}
#[test]
fn heap_binomial_push_min_3() {
let mut bh = BinomialHeap::init_min(0);
bh.push(1);
bh.push(2);
bh.push(3);
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: \nRank 1: \nRank 2: 0 1 2 3\n")
);
}
#[test]
fn heap_binomial_push_max_3() {
let mut bh = BinomialHeap::init_max(0);
bh.push(1);
bh.push(2);
bh.push(3);
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: \nRank 1: \nRank 2: 3 2 1 0\n")
);
}
#[test]
fn heap_binomial_pop_min_1() {
let mut bh = BinomialHeap::init_min(0);
bh.push(1);
bh.push(2);
bh.push(3);
let value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: 1\nRank 1: 2 3\nRank 2: \n")
);
assert_eq!(value, Some(0))
}
#[test]
fn heap_binomial_pop_max_1() {
let mut bh = BinomialHeap::init_max(0);
bh.push(1);
bh.push(2);
bh.push(3);
let value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: 2\nRank 1: 1 0\nRank 2: \n")
);
assert_eq!(value, Some(3))
}
#[test]
fn heap_binomial_pop_min_2() {
let mut bh = BinomialHeap::init_min(0);
bh.push(1);
bh.push(2);
bh.push(3);
bh.push(8);
bh.push(9);
bh.push(7);
let mut value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: \nRank 1: 2 3\nRank 2: 1 7 8 9\n")
);
assert_eq!(value, Some(0));
value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: 7\nRank 1: \nRank 2: 2 3 8 9\n")
);
assert_eq!(value, Some(1));
value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: \nRank 1: \nRank 2: 3 7 8 9\n")
);
assert_eq!(value, Some(2));
value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: 7\nRank 1: 8 9\nRank 2: \n")
);
assert_eq!(value, Some(3));
value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: \nRank 1: 8 9\nRank 2: \n")
);
assert_eq!(value, Some(7));
value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: 9\nRank 1: \nRank 2: \n")
);
assert_eq!(value, Some(8));
value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: \nRank 1: \nRank 2: \n")
);
assert_eq!(value, Some(9));
value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: \nRank 1: \nRank 2: \n")
);
assert_eq!(value, None);
}
#[test]
fn heap_binomial_pop_max_2() {
let mut bh = BinomialHeap::init_max(0);
bh.push(1);
bh.push(2);
bh.push(3);
bh.push(8);
bh.push(9);
bh.push(7);
let mut value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: \nRank 1: 8 7\nRank 2: 3 2 1 0\n")
);
assert_eq!(value, Some(9));
value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: 7\nRank 1: \nRank 2: 3 2 1 0\n")
);
assert_eq!(value, Some(8));
value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: \nRank 1: \nRank 2: 3 2 1 0\n")
);
assert_eq!(value, Some(7));
value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: 2\nRank 1: 1 0\nRank 2: \n")
);
assert_eq!(value, Some(3));
value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: \nRank 1: 1 0\nRank 2: \n")
);
assert_eq!(value, Some(2));
value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: 0\nRank 1: \nRank 2: \n")
);
assert_eq!(value, Some(1));
value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: \nRank 1: \nRank 2: \n")
);
assert_eq!(value, Some(0));
value = bh.pop();
assert_eq!(
BinomialHeap::preorder(&bh),
format!("Rank 0: \nRank 1: \nRank 2: \n")
);
assert_eq!(value, None);
}
#[test]
fn heap_binomial_merge_min_1() {
let bh1 = BinomialHeap::init_min(0);
let bh2 = BinomialHeap::init_min(1);
let merged_heap = BinomialHeap::merge(bh1, bh2);
assert_eq!(
BinomialHeap::preorder(&merged_heap),
format!("Rank 0: \nRank 1: 0 1\n")
);
}
#[test]
fn heap_binomial_merge_max_1() {
let bh1 = BinomialHeap::init_max(0);
let bh2 = BinomialHeap::init_max(1);
let merged_heap = BinomialHeap::merge(bh1, bh2);
assert_eq!(
BinomialHeap::preorder(&merged_heap),
format!("Rank 0: \nRank 1: 1 0\n")
);
}
#[test]
fn heap_binomial_merge_min_2() {
let bh1 = BinomialHeap::init_min(0);
let bh2 = BinomialHeap::init_min(1);
let merged_heap_1 = BinomialHeap::merge(bh1, bh2);
let bh3 = BinomialHeap::init_min(2);
let bh4 = BinomialHeap::init_min(3);
let merged_heap_2 = BinomialHeap::merge(bh3, bh4);
let merged_heap = BinomialHeap::merge(merged_heap_1, merged_heap_2);
assert_eq!(
BinomialHeap::preorder(&merged_heap),
format!("Rank 0: \nRank 1: \nRank 2: 0 1 2 3\n")
);
}
#[test]
fn heap_binomial_merge_max_2() {
let bh1 = BinomialHeap::init_max(0);
let bh2 = BinomialHeap::init_max(1);
let merged_heap_1 = BinomialHeap::merge(bh1, bh2);
let bh3 = BinomialHeap::init_max(2);
let bh4 = BinomialHeap::init_max(3);
let merged_heap_2 = BinomialHeap::merge(bh3, bh4);
let merged_heap = BinomialHeap::merge(merged_heap_1, merged_heap_2);
assert_eq!(
BinomialHeap::preorder(&merged_heap),
format!("Rank 0: \nRank 1: \nRank 2: 3 2 1 0\n")
);
}
#[test]
fn heap_binomial_peek_min_1() {
let bh1 = BinomialHeap::init_min(0);
assert_eq!(*bh1.peek(), Some(0));
assert_eq!(BinomialHeap::preorder(&bh1), format!("Rank 0: 0\n"));
}
#[test]
fn heap_binomial_peek_min_2() {
let bh1 = BinomialHeap::init_min(0);
let bh2 = BinomialHeap::init_min(1);
let merged_heap = BinomialHeap::merge(bh1, bh2);
assert_eq!(*merged_heap.peek(), Some(0));
assert_eq!(
BinomialHeap::preorder(&merged_heap),
format!("Rank 0: \nRank 1: 0 1\n")
);
}
#[test]
fn heap_binomial_peek_min_empty_heap() {
let bh1 = BinomialHeap::init_min(0);
let bh2 = BinomialHeap::init_min(1);
let mut merged_heap = BinomialHeap::merge(bh1, bh2);
merged_heap.pop();
merged_heap.pop();
assert_eq!(*merged_heap.peek(), None);
assert_eq!(
BinomialHeap::preorder(&merged_heap),
format!("Rank 0: \nRank 1: \n")
);
}
#[test]
fn heap_binomial_peek_max_1() {
let bh1 = BinomialHeap::init_max(0);
assert_eq!(*bh1.peek(), Some(0));
assert_eq!(BinomialHeap::preorder(&bh1), format!("Rank 0: 0\n"));
}
#[test]
fn heap_binomial_peek_max_2() {
let bh1 = BinomialHeap::init_max(0);
let bh2 = BinomialHeap::init_max(1);
let merged_heap = BinomialHeap::merge(bh1, bh2);
assert_eq!(*merged_heap.peek(), Some(1));
assert_eq!(
BinomialHeap::preorder(&merged_heap),
format!("Rank 0: \nRank 1: 1 0\n")
);
}
#[test]
fn heap_binomial_peek_max_empty_heap() {
let bh1 = BinomialHeap::init_max(0);
let bh2 = BinomialHeap::init_max(1);
let mut merged_heap = BinomialHeap::merge(bh1, bh2);
merged_heap.pop();
merged_heap.pop();
assert_eq!(*merged_heap.peek(), None);
assert_eq!(
BinomialHeap::preorder(&merged_heap),
format!("Rank 0: \nRank 1: \n")
);
}
#[test]
#[should_panic(expected = "Both binomial heaps must be of the same type(both min or both max)")]
fn heap_binomial_panic_merge() {
let bh1 = BinomialHeap::init_min(0);
let bh2 = BinomialHeap::init_max(1);
BinomialHeap::merge(bh1, bh2);
}
}