Min Heap
pop()
- Returns (inserted index, key) pair.
struct MinHeap<K> {
k: Vec<(u32, K)>,
pos: Vec<u32>,
max: usize,
}
impl<K> MinHeap<K>
where
K: PartialOrd + Copy,
{
fn new() -> Self {
Self {
k: vec![],
pos: vec![],
max: 0,
}
}
fn len(&self) -> usize {
self.k.len()
}
fn push(&mut self, k: K) {
let i = self.max;
let len = self.len() as u32;
self.max += 1;
self.k.push((i as u32, k));
self.pos.push(len);
self.up(i);
}
fn pop(&mut self) -> Option<(usize, K)> {
if self.len() == 0 {
return None;
}
let (i, k) = self.k.swap_remove(0);
if self.len() > 0 {
self.pos[self.k[0].0 as usize] = 0;
self.down(0);
}
Some((i as usize, k))
}
fn replace(&mut self, i: usize, k: K) -> K {
use std::cmp::Ordering::*;
let pos = self.pos[i] as usize;
let ordering = self.k[pos].1.partial_cmp(&k).unwrap();
let prev = std::mem::replace(&mut self.k[pos].1, k);
match ordering {
Greater => self.up(pos),
Less => self.down(pos),
Equal => {}
}
prev
}
fn up(&mut self, mut pos: usize) {
while pos > 0 {
let parent = (pos - 1) / 2;
if self.k[pos].1 >= self.k[parent].1 {
break;
}
self.k.swap(pos, parent);
self.pos[self.k[pos].0 as usize] = pos as u32;
pos = parent;
}
self.pos[self.k[pos].0 as usize] = pos as u32;
}
fn down(&mut self, mut pos: usize) {
let len = self.len();
loop {
let child = pos * 2 + 1;
if child >= len {
break;
}
let less = if child + 1 == len || self.k[child].1 <= self.k[child + 1].1 {
child
} else {
child + 1
};
if self.k[pos].1 <= self.k[less].1 {
break;
}
self.k.swap(less, pos);
self.pos[self.k[pos].0 as usize] = pos as u32;
pos = less;
}
self.pos[self.k[pos].0 as usize] = pos as u32;
}
}
impl<K> FromIterator<K> for MinHeap<K>
where
K: PartialOrd + Copy,
{
fn from_iter<T: IntoIterator<Item = K>>(iter: T) -> Self {
let k: Vec<_> = iter
.into_iter()
.enumerate()
.map(|(i, v)| (i as u32, v))
.collect();
let len = k.len();
let pos = (0..len as u32).collect();
let mut inst = Self { k, pos, max: len };
for i in (0..inst.len()).rev() {
inst.down(i);
}
inst
}
}
Example
Single Source Shortest Path (Dijkstra's)
fn sssp(g: &Graph, w: &[u32], s: usize) -> Vec<u32> {
let mut d = vec![u32::MAX; g.head.len()];
d[s] = 0;
let mut heap = d.iter().map(|&d| d).collect::<MinHeap<_>>();
while let Some((u, du)) = heap.pop() {
for (e, v) in g.neighbor(u) {
let dv = du + w[e >> 1] as u32;
if d[v] > dv {
d[v] = dv;
heap.replace(v, dv);
}
}
}
d
}