use alloc::vec::Vec;
pub type PriorityCompare<T> = fn(&T, &T) -> core::cmp::Ordering;
#[derive(Debug)]
pub struct PriorityQueue<T> {
data: Vec<T>,
compare: PriorityCompare<T>,
}
impl<T> PriorityQueue<T>
where
T: Clone,
{
pub fn new(compare: PriorityCompare<T>) -> Self {
Self { data: Vec::new(), compare }
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn push(&mut self, item: T) {
self.data.push(item);
self.up(self.data.len() - 1);
}
pub fn pop(&mut self) -> Option<T> {
if self.data.is_empty() {
return None;
}
let top = self.data.swap_remove(0);
if !self.data.is_empty() {
self.down(0);
}
Some(top)
}
pub fn peek(&self) -> Option<&T> {
self.data.first()
}
fn up(&mut self, mut pos: usize) {
let item = self.data[pos].clone();
while pos > 0 {
let parent = (pos - 1) / 2;
if (self.compare)(&self.data[parent], &item) != core::cmp::Ordering::Greater {
break;
}
self.data[pos] = self.data[parent].clone();
pos = parent;
}
self.data[pos] = item;
}
fn down(&mut self, mut pos: usize) {
let len = self.data.len();
let item = self.data[pos].clone();
let half_len = len / 2;
while pos < half_len {
let mut child = 2 * pos + 1;
if child + 1 < len
&& (self.compare)(&self.data[child + 1], &self.data[child])
== core::cmp::Ordering::Less
{
child += 1;
}
if (self.compare)(&self.data[child], &item) != core::cmp::Ordering::Less {
break;
}
self.data[pos] = self.data[child].clone();
pos = child;
}
self.data[pos] = item;
}
}