Initial commit

This commit is contained in:
hal8174 2023-12-06 21:25:03 +01:00
commit 7d47a10acf
18 changed files with 1545 additions and 0 deletions

176
src/priority_queue/mod.rs Normal file
View file

@ -0,0 +1,176 @@
pub mod fibonacci_heap;
pub trait PriorityQueue<Item>
where
Item: PartialOrd,
{
type Handle;
fn new() -> Self;
// fn with_capacity() -> Self {
// Self::new()
// }
fn insert(&mut self, item: Item) -> Self::Handle;
fn pop_min(&mut self) -> Option<Item>;
fn decrease_key(&mut self, handle: &Self::Handle, f: impl Fn(&mut Item));
}
#[derive(Debug)]
pub struct BinaryHeap<Item> {
data: Vec<Item>,
}
impl<Item> BinaryHeap<Item>
where
Item: PartialOrd,
{
fn downheap(&mut self, index: usize) {
let left = 2 * index + 1;
let right = 2 * index + 2;
if right < self.data.len() {
let smaller = if self.data[left] < self.data[right] {
left
} else {
right
};
if self.data[index] > self.data[smaller] {
self.data.swap(index, smaller);
self.downheap(smaller);
}
} else if left < self.data.len() && self.data[index] > self.data[left] {
self.data.swap(index, left);
self.downheap(left);
}
}
fn upheap(&mut self, index: usize) {
if index > 0 {
let parent = (index - 1) / 2;
if self.data[parent] > self.data[index] {
self.data.swap(parent, index);
self.upheap(parent);
}
}
}
fn search(&self, item: &Item) -> Option<usize> {
for (i, d) in self.data.iter().enumerate() {
if d == item {
return Some(i);
}
}
None
}
}
impl<Item> PriorityQueue<Item> for BinaryHeap<Item>
where
Item: PartialOrd + Clone,
{
type Handle = Item;
fn insert(&mut self, item: Item) -> Self::Handle {
self.data.push(item.clone());
self.upheap(self.data.len() - 1);
item
}
fn pop_min(&mut self) -> Option<Item> {
if self.data.is_empty() {
None
} else {
let d = self.data.swap_remove(0);
self.downheap(0);
Some(d)
}
}
fn decrease_key(&mut self, handle: &Self::Handle, f: impl Fn(&mut Item)) {
if let Some(index) = self.search(handle) {
f(&mut self.data[index]);
self.upheap(index);
}
}
fn new() -> Self {
Self { data: Vec::new() }
}
}
#[cfg(test)]
mod tests {
use super::PriorityQueue;
macro_rules! test_generics {
($($fun_mul:ident )+ ; $gen:ident $($gen_mul:ident)+) => {
test_generics!(@internal_mod $($fun_mul )*; $gen);
test_generics!($($fun_mul )*; $($gen_mul )*);
};
($($fun_mul:ident )+ ;$gen:ident) => {
test_generics!(@internal_mod $($fun_mul )*; $gen);
};
(@internal_mod $($fun_mul:ident )+; $gen:ident) => {
#[allow(non_snake_case)]
mod $gen {
test_generics!(@internal $($fun_mul )*; $gen);
}
};
(@internal $fun:ident $($fun_mul:ident )+; $gen:ident) => {
test_generics!(@internal $fun; $gen);
test_generics!(@internal $($fun_mul )*; $gen);
};
(@internal $fun:ident; $gen:ident) => {
#[test]
fn $fun() {
super::$fun::<super::super::$gen<usize>>();
}
}
}
test_generics!(basic_generic decrease_key_generic; BinaryHeap);
fn basic_generic<T: PriorityQueue<usize>>() {
let mut q = T::new();
q.insert(2);
q.insert(3);
q.insert(10);
q.insert(12);
q.insert(9);
q.insert(6);
q.insert(4);
q.insert(5);
q.insert(8);
q.insert(7);
q.insert(11);
q.insert(1);
assert_eq!(q.pop_min(), Some(1));
assert_eq!(q.pop_min(), Some(2));
assert_eq!(q.pop_min(), Some(3));
assert_eq!(q.pop_min(), Some(4));
assert_eq!(q.pop_min(), Some(5));
assert_eq!(q.pop_min(), Some(6));
assert_eq!(q.pop_min(), Some(7));
assert_eq!(q.pop_min(), Some(8));
assert_eq!(q.pop_min(), Some(9));
assert_eq!(q.pop_min(), Some(10));
assert_eq!(q.pop_min(), Some(11));
assert_eq!(q.pop_min(), Some(12));
assert_eq!(q.pop_min(), None);
}
fn decrease_key_generic<T: PriorityQueue<usize>>() {
let mut q = T::new();
q.insert(4);
let h = q.insert(5);
q.decrease_key(&h, |i| *i -= 3);
assert_eq!(q.pop_min(), Some(2));
assert_eq!(q.pop_min(), Some(4));
}
}