Skip to content

Commit

Permalink
Add rust mergeable heap
Browse files Browse the repository at this point in the history
  • Loading branch information
indy256 committed Aug 28, 2024
1 parent 0d43e13 commit 7f121ff
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 0 deletions.
1 change: 1 addition & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2021"

[dev-dependencies]
rstest="0.22.0"
rand = "0.8.5"

[lib]
path = "lib.rs"
76 changes: 76 additions & 0 deletions rust/structures/mergeable_heap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use std::fmt::Display;
use std::mem::swap;
use std::rc::Rc;

struct Heap<V> {
value: V,
left: Option<Rc<Heap<V>>>,
right: Option<Rc<Heap<V>>>,
}

impl<V: PartialOrd + Clone + Display> Heap<V> {
fn new(value: V) -> Option<Rc<Heap<V>>> {
Some(Rc::new(Self {
value,
left: None,
right: None,
}))
}
fn merge(a: &Option<Rc<Heap<V>>>, b: &Option<Rc<Heap<V>>>) -> Option<Rc<Heap<V>>> {
if a.is_none() {
return b.clone();
}
if b.is_none() {
return a.clone();
}
let mut ra = a.clone()?;
let mut rb = b.clone()?;
if ra.value > rb.value {
swap(&mut ra, &mut rb);
}
if rand::random() {
ra = Rc::new(Heap {
value: ra.value.clone(),
left: ra.right.clone(),
right: ra.left.clone(),
});
}
Some(Rc::new(Heap {
value: ra.value.clone(),
left: Self::merge(&ra.left.clone(), &Some(rb)),
right: ra.right.clone(),
}))
}

fn remove_min(heap: &Option<Rc<Heap<V>>>) -> (Option<Rc<Heap<V>>>, V) {
let h = heap.as_ref().unwrap();
(
Self::merge(&h.as_ref().left, &h.as_ref().right),
h.as_ref().value.clone(),
)
}

fn add(heap: &Option<Rc<Heap<V>>>, value: V) -> Option<Rc<Heap<V>>> {
Self::merge(heap, &Heap::new(value))
}
}

#[cfg(test)]
mod tests {
use crate::structures::mergeable_heap::Heap;

#[test]
fn basic_test() {
let mut h = None;
h = Heap::add(&h, 3);
h = Heap::add(&h, 1);
h = Heap::add(&h, 2);
let mut values = Vec::new();
while h.is_some() {
let (heap, min_value) = Heap::remove_min(&h);
values.push(min_value);
h = heap;
}
assert_eq!(values, [1, 2, 3]);
}
}
1 change: 1 addition & 0 deletions rust/structures/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod disjoint_sets;
pub mod fenwick_tree;
pub mod mergeable_heap;
pub mod persistent_tree;

0 comments on commit 7f121ff

Please sign in to comment.