factorio_blueprint/src/priority_queue/fibonacci_heap.rs

186 lines
4.8 KiB
Rust

use crate::misc::{Arena, ArenaKey};
use super::PriorityQueue;
#[derive(Debug)]
struct FibonacciHeapObject<T> {
left: ArenaKey,
right: ArenaKey,
parent: Option<ArenaKey>,
child: Option<ArenaKey>,
rank: usize,
marked: bool,
data: T,
}
#[derive(Debug)]
pub struct FibonacciHeap<T> {
arena: Arena<FibonacciHeapObject<T>>,
min: Option<ArenaKey>,
update_rank: Vec<Option<ArenaKey>>,
}
pub struct FibonacciHeapHandle(ArenaKey);
impl<T> PriorityQueue<T> for FibonacciHeap<T>
where
T: std::cmp::Ord,
{
type Handle = FibonacciHeapHandle;
fn new() -> Self {
todo!()
}
fn insert(&mut self, item: T) -> Self::Handle {
let h = self.arena.insert(FibonacciHeapObject {
left: ArenaKey::default(),
right: ArenaKey::default(),
parent: None,
child: None,
rank: 0,
marked: false,
data: item,
});
self.insert_tree(h);
FibonacciHeapHandle(h)
}
fn pop_min(&mut self) -> Option<T> {
if let Some(k) = self.min.take() {
let o = self.arena.remove(k);
if let Some(child) = o.child {
let mut p = child;
loop {
self.arena.get_mut(&p).parent = None;
self.arena.get_mut(&p).marked = false;
let t = self.arena.get(&p).right;
self.insert_tree(p);
p = t;
if p == child {
break;
}
}
}
if o.left != o.right {
self.arena.get_mut(&o.left).right = o.right;
self.arena.get_mut(&o.right).left = o.left;
self.update_min(o.left);
}
Some(o.data)
} else {
None
}
}
fn decrease_key(&mut self, _handle: &Self::Handle, _f: impl Fn(&mut T)) {
todo!()
}
}
impl<T> FibonacciHeap<T>
where
T: std::cmp::Ord,
{
fn insert_tree(&mut self, h: ArenaKey) {
if let Some(h_min) = self.min {
let h_last = self.arena.get(&h_min).left;
self.arena.get_mut(&h_min).left = h;
self.arena.get_mut(&h).left = h_last;
self.arena.get_mut(&h).right = h_min;
self.arena.get_mut(&h_last).right = h;
if self.arena.get(&h).data < self.arena.get(&h_min).data {
self.min = Some(h)
}
} else {
self.arena.get_mut(&h).left = h;
self.arena.get_mut(&h).right = h;
self.min = Some(h);
}
}
fn update_min(&mut self, mut h: ArenaKey) {
let h_start = h;
loop {
let next_h = self.arena.get(&h).right;
self.add_to_update_rank(h);
h = next_h;
if h == h_start {
break;
}
}
let mut prev = None;
// let mut start = None;
for h in &mut self.update_rank {
if let Some(h) = h.take() {
if let Some(p) = prev {
self.arena.get_mut(&h).left = p;
self.arena.get_mut(&p).right = h;
} else {
prev = Some(h);
// start = Some(h);
}
if let Some(m) = self.min {
if self.arena.get(&h).data < self.arena.get(&m).data {
self.min = Some(h);
}
} else {
self.min = Some(h);
}
}
}
}
fn add_to_update_rank(&mut self, h: ArenaKey) {
let rank = self.arena.get(&h).rank;
while self.update_rank.len() + 1 < rank {
self.update_rank.push(None)
}
if let Some(o) = self.update_rank.get_mut(rank).unwrap().take() {
if let Some(child) = self.arena.get(&h).child {
let last = self.arena.get(&child).left;
self.arena.get_mut(&child).left = h;
self.arena.get_mut(&last).right = h;
self.arena.get_mut(&o).parent = Some(h);
self.arena.get_mut(&o).marked = false;
self.arena.get_mut(&o).left = last;
self.arena.get_mut(&o).right = child;
} else {
self.arena.get_mut(&h).child = Some(o);
self.arena.get_mut(&o).parent = Some(h);
self.arena.get_mut(&o).marked = false;
self.arena.get_mut(&o).left = o;
self.arena.get_mut(&o).right = o;
}
self.arena.get_mut(&h).rank += 1;
self.add_to_update_rank(h);
} else {
*self.update_rank.get_mut(rank).unwrap() = Some(h);
}
}
}