#[cfg(not(has_std))]
use std::vec::Vec;
use crate::iterators::*;
use std::borrow::Borrow;
use std::cmp::{Eq, Ord};
#[cfg(has_std)]
use std::collections::hash_map::RandomState;
use std::hash::{BuildHasher, Hash};
use std::iter::{Extend, FromIterator, IntoIterator, Iterator};
use std::mem::{replace, swap};
use indexmap::map::{IndexMap, MutableKeys};
#[derive(Clone)]
#[cfg(has_std)]
pub struct PriorityQueue<I, P, H = RandomState>
where
I: Hash + Eq,
P: Ord,
{
pub(crate) map: IndexMap<I, P, H>,
heap: Vec<usize>,
qp: Vec<usize>,
size: usize,
}
#[derive(Clone)]
#[cfg(not(has_std))]
pub struct PriorityQueue<I, P, H>
where
I: Hash + Eq,
P: Ord,
{
pub(crate) map: IndexMap<I, P, H>,
heap: Vec<usize>,
qp: Vec<usize>,
size: usize,
}
impl<I, P, H> Eq for PriorityQueue<I, P, H>
where
I: Hash + Eq,
P: Ord,
H: BuildHasher,
{
}
impl<I, P, H> Default for PriorityQueue<I, P, H>
where
I: Hash + Eq,
P: Ord,
H: BuildHasher + Default,
{
fn default() -> Self {
Self::with_default_hasher()
}
}
#[cfg(has_std)]
impl<I, P> PriorityQueue<I, P>
where
P: Ord,
I: Hash + Eq,
{
pub fn new() -> Self {
Self::with_capacity(0)
}
pub fn with_capacity(capacity: usize) -> Self {
Self::with_capacity_and_default_hasher(capacity)
}
}
impl<I, P, H> PriorityQueue<I, P, H>
where
P: Ord,
I: Hash + Eq,
H: BuildHasher + Default,
{
pub fn with_default_hasher() -> Self {
Self::with_capacity_and_default_hasher(0)
}
pub fn with_capacity_and_default_hasher(capacity: usize) -> Self {
Self::with_capacity_and_hasher(capacity, H::default())
}
}
impl<I, P, H> PriorityQueue<I, P, H>
where
P: Ord,
I: Hash + Eq,
H: BuildHasher,
{
pub fn with_hasher(hash_builder: H) -> Self {
Self::with_capacity_and_hasher(0, hash_builder)
}
pub fn with_capacity_and_hasher(capacity: usize, hash_builder: H) -> Self {
Self {
map: IndexMap::with_capacity_and_hasher(capacity, hash_builder),
heap: Vec::with_capacity(capacity),
qp: Vec::with_capacity(capacity),
size: 0,
}
}
pub fn iter(&self) -> crate::pqueue::Iter<I, P> {
crate::pqueue::Iter {
iter: self.map.iter(),
}
}
}
impl<I, P, H> PriorityQueue<I, P, H>
where
P: Ord,
I: Hash + Eq,
{
pub fn iter_mut(&mut self) -> crate::pqueue::IterMut<I, P, H> {
crate::pqueue::IterMut::new(self)
}
pub fn peek(&self) -> Option<(&I, &P)> {
if self.size == 0 {
return None;
}
self.map.get_index(unsafe { *self.heap.get_unchecked(0) })
}
pub fn peek_mut(&mut self) -> Option<(&mut I, &P)> {
if self.size == 0 {
return None;
}
self.map
.get_index_mut(unsafe { *self.heap.get_unchecked(0) })
.map(|(k, v)| (k, &*v))
}
pub fn capacity(&self) -> usize {
self.map.capacity()
}
}
impl<I, P, H> PriorityQueue<I, P, H>
where
P: Ord,
I: Hash + Eq,
H: BuildHasher,
{
pub fn reserve(&mut self, additional: usize) {
self.map.reserve(additional);
self.heap.reserve(additional);
self.qp.reserve(additional);
}
}
impl<I, P, H> PriorityQueue<I, P, H>
where
P: Ord,
I: Hash + Eq,
{
pub fn shrink_to_fit(&mut self) {
self.heap.shrink_to_fit();
self.qp.shrink_to_fit();
}
pub fn pop(&mut self) -> Option<(I, P)> {
match self.size {
0 => None,
1 => self.swap_remove(),
_ => {
let r = self.swap_remove();
self.heapify(0);
r
}
}
}
}
impl<I, P, H> PriorityQueue<I, P, H>
where
P: Ord,
I: Hash + Eq,
H: BuildHasher,
{
pub fn push(&mut self, item: I, priority: P) -> Option<P> {
use indexmap::map::Entry::*;
let mut pos = 0;
let mut oldp = None;
match self.map.entry(item) {
Occupied(mut e) => {
oldp = Some(replace(e.get_mut(), priority));
pos = unsafe { *self.qp.get_unchecked(e.index()) };
}
Vacant(e) => {
e.insert(priority);
}
}
if oldp.is_some() {
unsafe {
let tmp = *self.heap.get_unchecked(pos);
while (pos > 0)
&& (self
.map
.get_index(*self.heap.get_unchecked(parent(pos)))
.unwrap()
.1
< self.map.get_index(tmp).unwrap().1)
{
*self.heap.get_unchecked_mut(pos) = *self.heap.get_unchecked(parent(pos));
*self.qp.get_unchecked_mut(*self.heap.get_unchecked(pos)) = pos;
pos = parent(pos);
}
*self.heap.get_unchecked_mut(pos) = tmp;
*self.qp.get_unchecked_mut(tmp) = pos;
}
self.heapify(pos);
return oldp;
}
let priority = self.map.get_index(self.size).unwrap().1;
let mut i = self.size;
let k = i;
self.qp.push(i);
self.heap.push(0);
unsafe {
while (i > 0)
&& (self
.map
.get_index(*self.heap.get_unchecked(parent(i)))
.unwrap()
.1
< priority)
{
*self.heap.get_unchecked_mut(i) = *self.heap.get_unchecked(parent(i));
*self.qp.get_unchecked_mut(*self.heap.get_unchecked(i)) = i;
i = parent(i);
}
*self.heap.get_unchecked_mut(i) = k;
*self.qp.get_unchecked_mut(k) = i;
}
self.size += 1;
None
}
pub fn push_increase(&mut self, item: I, priority: P) -> Option<P> {
if self.get_priority(&item).map_or(true, |p| priority > *p) {
self.push(item, priority)
} else {
Some(priority)
}
}
pub fn push_decrease(&mut self, item: I, priority: P) -> Option<P> {
if self.get_priority(&item).map_or(true, |p| priority < *p) {
self.push(item, priority)
} else {
Some(priority)
}
}
pub fn change_priority<Q: ?Sized>(&mut self, item: &Q, mut new_priority: P) -> Option<P>
where
I: Borrow<Q>,
Q: Eq + Hash,
{
let mut pos;
let r = if let Some((index, _, p)) = self.map.get_full_mut(item) {
swap(p, &mut new_priority);
pos = unsafe { *self.qp.get_unchecked(index) };
Some(new_priority)
} else {
return None;
};
if r.is_some() {
unsafe {
let tmp = *self.heap.get_unchecked(pos);
while (pos > 0)
&& (self
.map
.get_index(*self.heap.get_unchecked(parent(pos)))
.unwrap()
.1
< self.map.get_index(tmp).unwrap().1)
{
*self.heap.get_unchecked_mut(pos) = *self.heap.get_unchecked(parent(pos));
*self.qp.get_unchecked_mut(*self.heap.get_unchecked(pos)) = pos;
pos = parent(pos);
}
*self.heap.get_unchecked_mut(pos) = tmp;
*self.qp.get_unchecked_mut(tmp) = pos;
}
self.heapify(pos);
}
r
}
pub fn change_priority_by<Q: ?Sized, F>(&mut self, item: &Q, priority_setter: F)
where
I: Borrow<Q>,
Q: Eq + Hash,
F: FnOnce(&mut P),
{
let mut pos = 0;
let mut found = false;
if let Some((index, _, mut p)) = self.map.get_full_mut(item) {
priority_setter(&mut p);
pos = unsafe { *self.qp.get_unchecked(index) };
found = true;
}
if found {
unsafe {
let tmp = *self.heap.get_unchecked(pos);
while (pos > 0)
&& (self
.map
.get_index(*self.heap.get_unchecked(parent(pos)))
.unwrap()
.1
< self.map.get_index(tmp).unwrap().1)
{
*self.heap.get_unchecked_mut(pos) = *self.heap.get_unchecked(parent(pos));
*self.qp.get_unchecked_mut(*self.heap.get_unchecked(pos)) = pos;
pos = parent(pos);
}
*self.heap.get_unchecked_mut(pos) = tmp;
*self.qp.get_unchecked_mut(tmp) = pos;
}
self.heapify(pos);
}
}
pub fn get_priority<Q: ?Sized>(&self, item: &Q) -> Option<&P>
where
I: Borrow<Q>,
Q: Eq + Hash,
{
self.map.get(item)
}
pub fn get<Q>(&self, item: &Q) -> Option<(&I, &P)>
where
I: Borrow<Q>,
Q: Eq + Hash,
{
self.map.get_full(item).map(|(_, k, v)| (k, v))
}
pub fn get_mut<Q>(&mut self, item: &Q) -> Option<(&mut I, &P)>
where
I: Borrow<Q>,
Q: Eq + Hash,
{
self.map.get_full_mut2(item).map(|(_, k, v)| (k, &*v))
}
pub fn remove<Q>(&mut self, item: &Q) -> Option<(I, P)>
where
I: Borrow<Q>,
Q: Eq + Hash,
{
let element = self.map.swap_remove_full(item);
if let Some((i, _, _)) = element {
self.size -= 1;
let pos = self.qp.swap_remove(i);
self.heap.swap_remove(pos);
if i < self.size {
unsafe {
let qpi = self.qp.get_unchecked_mut(i);
if *qpi == self.size {
*qpi = pos;
} else {
*self.heap.get_unchecked_mut(*qpi) = i;
}
}
}
if pos < self.size {
unsafe {
let heap_pos = self.heap.get_unchecked_mut(pos);
if *heap_pos == self.size {
*heap_pos = i;
} else {
*self.qp.get_unchecked_mut(*heap_pos) = pos;
}
}
self.heapify(pos);
}
}
element.map(|(_, i, p)| (i, p))
}
pub fn into_vec(self) -> Vec<I> {
self.map.into_iter().map(|(i, _)| i).collect()
}
}
impl<I, P, H> PriorityQueue<I, P, H>
where
P: Ord,
I: Hash + Eq,
{
pub fn into_sorted_vec(mut self) -> Vec<I> {
let mut res = Vec::with_capacity(self.size);
while let Some((i, _)) = self.pop() {
res.push(i);
}
res
}
pub fn len(&self) -> usize {
self.size
}
pub fn is_empty(&self) -> bool {
self.size == 0
}
}
impl<I, P, H> PriorityQueue<I, P, H>
where
P: Ord,
I: Hash + Eq,
H: BuildHasher,
{
pub fn clear(&mut self) {
self.heap.clear();
self.qp.clear();
self.map.clear();
self.size = 0;
}
pub fn append(&mut self, other: &mut Self) {
if other.size > self.size {
std::mem::swap(self, other);
}
if other.size == 0 {
return;
}
let drain = other.map.drain(..);
for (k, v) in drain {
if !self.map.contains_key(&k) {
let i = self.size;
self.map.insert(k, v);
self.heap.push(i);
self.qp.push(i);
self.size += 1;
}
}
other.heap.clear();
other.qp.clear();
self.heap_build();
}
}
impl<I, P, H> PriorityQueue<I, P, H>
where
P: Ord,
I: Hash + Eq,
{
pub fn into_sorted_iter(self) -> IntoSortedIter<I, P, H> {
IntoSortedIter { pq: self }
}
fn swap_remove(&mut self) -> Option<(I, P)> {
let head = self.heap.swap_remove(0);
self.size -= 1;
if self.size == 0 {
self.qp.pop();
return self.map.swap_remove_index(head);
}
unsafe {
*self.qp.get_unchecked_mut(*self.heap.get_unchecked(0)) = 0;
}
self.qp.swap_remove(head);
if head < self.size {
unsafe {
*self.heap.get_unchecked_mut(*self.qp.get_unchecked(head)) = head;
}
}
self.map.swap_remove_index(head)
}
fn swap(&mut self, a: usize, b: usize) {
let (i, j) = unsafe { (*self.heap.get_unchecked(a), *self.heap.get_unchecked(b)) };
self.heap.swap(a, b);
self.qp.swap(i, j);
}
fn heapify(&mut self, i: usize) {
let (mut l, mut r) = (left(i), right(i));
let mut i = i;
let mut largest = if l < self.size
&& unsafe {
self.map.get_index(*self.heap.get_unchecked(l)).unwrap().1
> self.map.get_index(*self.heap.get_unchecked(i)).unwrap().1
} {
l
} else {
i
};
if r < self.size
&& unsafe {
self.map.get_index(*self.heap.get_unchecked(r)).unwrap().1
> self
.map
.get_index(*self.heap.get_unchecked(largest))
.unwrap()
.1
}
{
largest = r;
}
while largest != i {
self.swap(i, largest);
i = largest;
l = left(i);
r = right(i);
if l < self.size
&& unsafe {
self.map.get_index(*self.heap.get_unchecked(l)).unwrap().1
> self.map.get_index(*self.heap.get_unchecked(i)).unwrap().1
}
{
largest = l;
} else {
largest = i;
}
if r < self.size
&& unsafe {
self.map.get_index(*self.heap.get_unchecked(r)).unwrap().1
> self
.map
.get_index(*self.heap.get_unchecked(largest))
.unwrap()
.1
}
{
largest = r;
}
}
}
pub(crate) fn heap_build(&mut self) {
if self.size == 0 {
return;
}
for i in (0..=parent(self.size)).rev() {
self.heapify(i);
}
}
}
impl<I, P, H> From<Vec<(I, P)>> for PriorityQueue<I, P, H>
where
I: Hash + Eq,
P: Ord,
H: BuildHasher + Default,
{
fn from(vec: Vec<(I, P)>) -> Self {
let mut pq = Self::with_capacity_and_hasher(vec.len(), <_>::default());
let mut i = 0;
for (item, priority) in vec {
if !pq.map.contains_key(&item) {
pq.map.insert(item, priority);
pq.qp.push(i);
pq.heap.push(i);
i += 1;
}
}
pq.size = i;
pq.heap_build();
pq
}
}
impl<I, P, H> FromIterator<(I, P)> for PriorityQueue<I, P, H>
where
I: Hash + Eq,
P: Ord,
H: BuildHasher + Default,
{
fn from_iter<IT>(iter: IT) -> Self
where
IT: IntoIterator<Item = (I, P)>,
{
let iter = iter.into_iter();
let (min, max) = iter.size_hint();
let mut pq = if let Some(max) = max {
Self::with_capacity_and_hasher(max, <_>::default())
} else if min > 0 {
Self::with_capacity_and_hasher(min, <_>::default())
} else {
Self::with_hasher(<_>::default())
};
for (item, priority) in iter {
if pq.map.contains_key(&item) {
let (_, old_item, old_priority) = pq.map.get_full_mut2(&item).unwrap();
*old_item = item;
*old_priority = priority;
} else {
pq.map.insert(item, priority);
pq.qp.push(pq.size);
pq.heap.push(pq.size);
pq.size += 1;
}
}
pq.heap_build();
pq
}
}
impl<I, P, H> IntoIterator for PriorityQueue<I, P, H>
where
I: Hash + Eq,
P: Ord,
H: BuildHasher,
{
type Item = (I, P);
type IntoIter = crate::pqueue::IntoIter<I, P>;
fn into_iter(self) -> crate::pqueue::IntoIter<I, P> {
crate::pqueue::IntoIter {
iter: self.map.into_iter(),
}
}
}
impl<'a, I, P, H> IntoIterator for &'a PriorityQueue<I, P, H>
where
I: Hash + Eq,
P: Ord,
H: BuildHasher,
{
type Item = (&'a I, &'a P);
type IntoIter = Iter<'a, I, P>;
fn into_iter(self) -> Iter<'a, I, P> {
Iter {
iter: self.map.iter(),
}
}
}
impl<'a, I, P, H> IntoIterator for &'a mut PriorityQueue<I, P, H>
where
I: Hash + Eq,
P: Ord,
{
type Item = (&'a mut I, &'a mut P);
type IntoIter = IterMut<'a, I, P, H>;
fn into_iter(self) -> IterMut<'a, I, P, H> {
IterMut::new(self)
}
}
impl<I, P, H> Extend<(I, P)> for PriorityQueue<I, P, H>
where
I: Hash + Eq,
P: Ord,
H: BuildHasher,
{
fn extend<T: IntoIterator<Item = (I, P)>>(&mut self, iter: T) {
let iter = iter.into_iter();
let (min, max) = iter.size_hint();
let mut rebuild = false;
if let Some(max) = max {
self.reserve(max);
rebuild = better_to_rebuild(self.size, max);
} else if min != 0 {
self.reserve(min);
rebuild = better_to_rebuild(self.size, min);
}
if rebuild {
for (item, priority) in iter {
if self.map.contains_key(&item) {
let (_, old_item, old_priority) = self.map.get_full_mut2(&item).unwrap();
*old_item = item;
*old_priority = priority;
} else {
self.map.insert(item, priority);
self.qp.push(self.size);
self.heap.push(self.size);
self.size += 1;
}
}
self.heap_build();
} else {
for (item, priority) in iter {
self.push(item, priority);
}
}
}
}
use std::fmt;
impl<I, P, H> fmt::Debug for PriorityQueue<I, P, H>
where
I: fmt::Debug + Hash + Eq,
P: fmt::Debug + Ord,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_map()
.entries(self.heap.iter().map(|&i| self.map.get_index(i).unwrap()))
.finish()
}
}
use std::cmp::PartialEq;
impl<I, P1, H1, P2, H2> PartialEq<PriorityQueue<I, P2, H2>> for PriorityQueue<I, P1, H1>
where
I: Hash + Eq,
P1: Ord,
P1: PartialEq<P2>,
Option<P1>: PartialEq<Option<P2>>,
P2: Ord,
H1: BuildHasher,
H2: BuildHasher,
{
fn eq(&self, other: &PriorityQueue<I, P2, H2>) -> bool {
self.map == other.map
}
}
fn left(i: usize) -> usize {
(i * 2) + 1
}
fn right(i: usize) -> usize {
(i * 2) + 2
}
fn parent(i: usize) -> usize {
(i - 1) / 2
}
fn log2_fast(x: usize) -> usize {
use std::mem::size_of;
8 * size_of::<usize>() - (x.leading_zeros() as usize) - 1
}
fn better_to_rebuild(len1: usize, len2: usize) -> bool {
if len1 <= 1 {
return false;
}
2 * (len1 + len2) < len2 * log2_fast(len1)
}
#[cfg(feature = "serde")]
mod serde {
use crate::pqueue::PriorityQueue;
use std::cmp::{Eq, Ord};
use std::collections::hash_map::RandomState;
use std::hash::{BuildHasher, Hash};
use std::marker::PhantomData;
use serde::ser::{Serialize, SerializeSeq, Serializer};
impl<I, P, H> Serialize for PriorityQueue<I, P, H>
where
I: Hash + Eq + Serialize,
P: Ord + Serialize,
H: BuildHasher,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut map_serializer = serializer.serialize_seq(Some(self.size))?;
for (k, v) in &self.map {
map_serializer.serialize_element(&(k, v))?;
}
map_serializer.end()
}
}
use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
impl<'de, I, P, H> Deserialize<'de> for PriorityQueue<I, P, H>
where
I: Hash + Eq + Deserialize<'de>,
P: Ord + Deserialize<'de>,
H: BuildHasher + Default,
{
fn deserialize<D>(deserializer: D) -> Result<PriorityQueue<I, P, H>, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(PQVisitor {
marker: PhantomData,
})
}
}
struct PQVisitor<I, P, H = RandomState>
where
I: Hash + Eq,
P: Ord,
{
marker: PhantomData<PriorityQueue<I, P, H>>,
}
impl<'de, I, P, H> Visitor<'de> for PQVisitor<I, P, H>
where
I: Hash + Eq + Deserialize<'de>,
P: Ord + Deserialize<'de>,
H: BuildHasher + Default,
{
type Value = PriorityQueue<I, P, H>;
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(formatter, "A priority queue")
}
fn visit_unit<E>(self) -> Result<Self::Value, E> {
Ok(PriorityQueue::with_default_hasher())
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut pq: PriorityQueue<I, P, H> = if let Some(size) = seq.size_hint() {
PriorityQueue::with_capacity_and_default_hasher(size)
} else {
PriorityQueue::with_default_hasher()
};
while let Some((item, priority)) = seq.next_element()? {
pq.map.insert(item, priority);
pq.qp.push(pq.size);
pq.heap.push(pq.size);
pq.size += 1;
}
pq.heap_build();
Ok(pq)
}
}
}