#![allow(dead_code)]
#[derive(Debug, Clone)]
struct LeftistNode<K: Ord + Clone, V: Clone> {
key: K,
val: V,
rank: usize,
left: Option<Box<LeftistNode<K, V>>>,
right: Option<Box<LeftistNode<K, V>>>,
}
impl<K: Ord + Clone, V: Clone> LeftistNode<K, V> {
fn new(key: K, val: V) -> Box<Self> {
Box::new(LeftistNode {
key,
val,
rank: 1,
left: None,
right: None,
})
}
fn rank(node: &Option<Box<LeftistNode<K, V>>>) -> usize {
node.as_ref().map_or(0, |n| n.rank)
}
fn merge(
a: Option<Box<LeftistNode<K, V>>>,
b: Option<Box<LeftistNode<K, V>>>,
) -> Option<Box<LeftistNode<K, V>>> {
match (a, b) {
(None, x) | (x, None) => x,
(Some(mut ha), Some(hb)) => {
if ha.key > hb.key {
return Self::merge(Some(hb), Some(ha));
}
ha.right = Self::merge(ha.right.take(), Some(hb));
if Self::rank(&ha.left) < Self::rank(&ha.right) {
std::mem::swap(&mut ha.left, &mut ha.right);
}
ha.rank = Self::rank(&ha.right) + 1;
Some(ha)
}
}
}
}
pub struct LeftistHeap<K: Ord + Clone, V: Clone> {
root: Option<Box<LeftistNode<K, V>>>,
count: usize,
}
impl<K: Ord + Clone, V: Clone> LeftistHeap<K, V> {
pub fn new() -> Self {
LeftistHeap {
root: None,
count: 0,
}
}
pub fn insert(&mut self, key: K, val: V) {
let node = Some(LeftistNode::new(key, val));
self.root = LeftistNode::merge(self.root.take(), node);
self.count += 1;
}
pub fn peek_min(&self) -> Option<(&K, &V)> {
self.root.as_ref().map(|r| (&r.key, &r.val))
}
pub fn extract_min(&mut self) -> Option<(K, V)> {
let root = self.root.take()?;
self.root = LeftistNode::merge(root.left, root.right);
self.count = self.count.saturating_sub(1);
Some((root.key, root.val))
}
pub fn len(&self) -> usize {
self.count
}
pub fn is_empty(&self) -> bool {
self.count == 0
}
pub fn merge_with(&mut self, other: LeftistHeap<K, V>) {
self.count += other.count;
self.root = LeftistNode::merge(self.root.take(), other.root);
}
pub fn root_rank(&self) -> usize {
self.root.as_ref().map_or(0, |r| r.rank)
}
}
impl<K: Ord + Clone, V: Clone> Default for LeftistHeap<K, V> {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_insert_and_peek() {
let mut h: LeftistHeap<u32, u32> = LeftistHeap::new();
h.insert(7, 70);
h.insert(3, 30);
let (k, _) = h.peek_min().expect("should succeed");
assert_eq!(*k, 3 );
}
#[test]
fn test_extract_min() {
let mut h: LeftistHeap<u32, u32> = LeftistHeap::new();
h.insert(9, 90);
h.insert(4, 40);
let (k, v) = h.extract_min().expect("should succeed");
assert_eq!(k, 4 );
assert_eq!(v, 40);
}
#[test]
fn test_len() {
let mut h: LeftistHeap<u32, u32> = LeftistHeap::new();
h.insert(1, 1);
h.insert(2, 2);
assert_eq!(h.len(), 2);
}
#[test]
fn test_is_empty() {
let h: LeftistHeap<u32, u32> = LeftistHeap::new();
assert!(h.is_empty());
}
#[test]
fn test_sorted_extraction() {
let mut h: LeftistHeap<u32, u32> = LeftistHeap::new();
for v in [5u32, 2, 8, 1, 4] {
h.insert(v, v);
}
let mut prev = 0u32;
while let Some((k, _)) = h.extract_min() {
assert!(k >= prev );
prev = k;
}
}
#[test]
fn test_merge_with() {
let mut a: LeftistHeap<u32, u32> = LeftistHeap::new();
let mut b: LeftistHeap<u32, u32> = LeftistHeap::new();
a.insert(10, 10);
b.insert(3, 3);
a.merge_with(b);
let (k, _) = a.peek_min().expect("should succeed");
assert_eq!(*k, 3 );
}
#[test]
fn test_empty_extract() {
let mut h: LeftistHeap<u32, u32> = LeftistHeap::new();
assert!(h.extract_min().is_none());
}
#[test]
fn test_root_rank() {
let mut h: LeftistHeap<u32, u32> = LeftistHeap::new();
h.insert(1, 1);
h.insert(2, 2);
assert!(h.root_rank() >= 1 );
}
#[test]
fn test_default() {
let h: LeftistHeap<u32, u32> = LeftistHeap::default();
assert!(h.is_empty());
}
}