pub mod iterators;
#[cfg(not(feature = "std"))]
use std::vec::Vec;
use crate::better_to_rebuild;
use crate::core_iterators::*;
use crate::store::{left, parent, right};
use crate::store::{Index, Position, Store};
use crate::TryReserveError;
use equivalent::Equivalent;
use iterators::*;
use std::cmp::{Eq, Ord};
#[cfg(feature = "std")]
use std::collections::hash_map::RandomState;
use std::hash::{BuildHasher, Hash};
use std::iter::{Extend, FromIterator, IntoIterator, Iterator};
use std::mem::replace;
#[derive(Clone, Debug)]
#[cfg(feature = "std")]
pub struct PriorityQueue<I, P, H = RandomState> {
pub(crate) store: Store<I, P, H>,
}
#[derive(Clone, Debug)]
#[cfg(not(feature = "std"))]
pub struct PriorityQueue<I, P, H> {
pub(crate) store: Store<I, P, H>,
}
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(feature = "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 const fn with_hasher(hash_builder: H) -> Self {
Self {
store: Store::with_hasher(hash_builder),
}
}
pub fn with_capacity_and_hasher(capacity: usize, hash_builder: H) -> Self {
Self {
store: Store::with_capacity_and_hasher(capacity, hash_builder),
}
}
}
impl<I, P, H> PriorityQueue<I, P, H> {
pub fn iter(&self) -> Iter<'_, I, P> {
self.store.iter()
}
pub fn shrink_to_fit(&mut self) {
self.store.shrink_to_fit();
}
pub fn drain(&mut self) -> Drain<'_, I, P> {
self.store.drain()
}
pub fn peek(&self) -> Option<(&I, &P)> {
self.store
.heap
.first()
.and_then(|index| self.store.map.get_index(index.0))
}
pub fn capacity(&self) -> usize {
self.store.capacity()
}
#[inline]
pub fn len(&self) -> usize {
self.store.len()
}
pub fn is_empty(&self) -> bool {
self.store.is_empty()
}
pub fn into_vec(self) -> Vec<I> {
self.store.into_vec()
}
pub fn clear(&mut self) {
self.store.clear();
}
pub fn reserve(&mut self, additional: usize) {
self.store.reserve(additional);
}
pub fn reserve_exact(&mut self, additional: usize) {
self.store.reserve_exact(additional);
}
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.store.try_reserve(additional)
}
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.store.try_reserve_exact(additional)
}
}
impl<I, P, H> PriorityQueue<I, P, H>
where
P: Ord,
{
pub fn iter_mut(&mut self) -> IterMut<'_, I, P, H> {
IterMut::new(self)
}
pub fn pop(&mut self) -> Option<(I, P)> {
match self.len() {
0 => None,
1 => self.store.swap_remove(Position(0)),
_ => {
let r = self.store.swap_remove(Position(0));
self.heapify(Position(0));
r
}
}
}
pub fn into_sorted_vec(mut self) -> Vec<I> {
let mut res = Vec::with_capacity(self.store.size);
while let Some((i, _)) = self.pop() {
res.push(i);
}
res
}
pub fn into_sorted_iter(self) -> IntoSortedIter<I, P, H> {
IntoSortedIter { pq: self }
}
}
impl<I, P, H> PriorityQueue<I, P, H>
where
P: Ord,
I: Hash + Eq,
H: BuildHasher,
{
pub fn retain<F>(&mut self, predicate: F)
where
F: FnMut(&I, &P) -> bool,
{
self.store.retain(predicate);
self.heap_build();
}
pub fn retain_mut<F>(&mut self, predicate: F)
where
F: FnMut(&mut I, &mut P) -> bool,
{
self.store.retain_mut(predicate);
self.heap_build();
}
pub fn extract_if<F>(&mut self, predicate: F) -> ExtractIf<'_, I, P, F, H>
where
F: FnMut(&mut I, &mut P) -> bool,
{
ExtractIf::new(self, predicate)
}
pub fn pop_if<F>(&mut self, predicate: F) -> Option<(I, P)>
where
F: FnOnce(&mut I, &mut P) -> bool,
{
match self.len() {
0 => None,
1 => self.store.swap_remove_if(Position(0), predicate),
_ => {
let r = self.store.swap_remove_if(Position(0), predicate);
self.heapify(Position(0));
r
}
}
}
pub fn push(&mut self, item: I, priority: P) -> Option<P> {
use indexmap::map::Entry::*;
let mut pos = Position(0);
let mut oldp = None;
match self.store.map.entry(item) {
Occupied(mut e) => {
oldp = Some(replace(e.get_mut(), priority));
pos = unsafe { *self.store.qp.get_unchecked(e.index()) };
}
Vacant(e) => {
e.insert(priority);
}
}
if oldp.is_some() {
self.up_heapify(pos);
return oldp;
}
let i = self.len();
self.store.qp.push(Position(i));
self.store.heap.push(Index(i));
self.bubble_up(Position(i), Index(i));
self.store.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>(&mut self, item: &Q, new_priority: P) -> Option<P>
where
Q: ?Sized + Equivalent<I> + Hash,
{
self.store
.change_priority(item, new_priority)
.map(|(r, pos)| {
self.up_heapify(pos);
r
})
}
pub fn change_priority_by<Q, F>(&mut self, item: &Q, priority_setter: F) -> bool
where
Q: ?Sized + Equivalent<I> + Hash,
F: FnOnce(&mut P),
{
self.store
.change_priority_by(item, priority_setter)
.map(|pos| {
self.up_heapify(pos);
})
.is_some()
}
pub fn get_priority<Q>(&self, item: &Q) -> Option<&P>
where
Q: ?Sized + Equivalent<I> + Hash,
{
self.store.get_priority(item)
}
pub fn contains<Q>(&self, item: &Q) -> bool
where
Q: ?Sized + Equivalent<I> + Hash,
{
self.store.contains(item)
}
pub fn get<Q>(&self, item: &Q) -> Option<(&I, &P)>
where
Q: ?Sized + Equivalent<I> + Hash,
{
self.store.get(item)
}
pub fn get_mut<Q>(&mut self, item: &Q) -> Option<(&mut I, &P)>
where
Q: ?Sized + Equivalent<I> + Hash,
{
self.store.get_mut(item)
}
pub fn peek_mut(&mut self) -> Option<(&mut I, &P)> {
use indexmap::map::MutableKeys;
if self.store.size == 0 {
return None;
}
self.store
.map
.get_index_mut2(unsafe { self.store.heap.get_unchecked(0) }.0)
.map(|(k, v)| (k, &*v))
}
pub fn remove<Q>(&mut self, item: &Q) -> Option<(I, P)>
where
Q: ?Sized + Equivalent<I> + Hash,
{
self.store.remove(item).map(|(item, priority, pos)| {
if pos.0 < self.len() {
self.up_heapify(pos);
}
(item, priority)
})
}
pub fn append(&mut self, other: &mut Self) {
self.store.append(&mut other.store);
self.heap_build();
}
}
impl<I, P, H> PriorityQueue<I, P, H>
where
P: Ord,
{
fn heapify(&mut self, mut i: Position) {
if self.len() <= 1 {
return;
}
let (mut l, mut r) = (left(i), right(i));
let mut largest = i;
let mut largestp = unsafe { self.store.get_priority_from_position(i) };
if l.0 < self.len() {
let childp = unsafe { self.store.get_priority_from_position(l) };
if childp > largestp {
largest = l;
largestp = childp;
}
if r.0 < self.len() && unsafe { self.store.get_priority_from_position(r) } > largestp {
largest = r;
}
}
while largest != i {
self.store.swap(i, largest);
i = largest;
largestp = unsafe { self.store.get_priority_from_position(i) };
l = left(i);
if l.0 < self.len() {
let childp = unsafe { self.store.get_priority_from_position(l) };
if childp > largestp {
largest = l;
largestp = childp;
}
r = right(i);
if r.0 < self.len()
&& unsafe { self.store.get_priority_from_position(r) } > largestp
{
largest = r;
}
}
}
}
fn bubble_up(&mut self, mut position: Position, map_position: Index) -> Position {
let priority = self.store.map.get_index(map_position.0).unwrap().1;
let mut parent_position = Position(0);
while if position.0 > 0 {
parent_position = parent(position);
(unsafe { self.store.get_priority_from_position(parent_position) }) < priority
} else {
false
} {
unsafe {
let parent_index = *self.store.heap.get_unchecked(parent_position.0);
*self.store.heap.get_unchecked_mut(position.0) = parent_index;
*self.store.qp.get_unchecked_mut(parent_index.0) = position;
}
position = parent_position;
}
unsafe {
*self.store.heap.get_unchecked_mut(position.0) = map_position;
*self.store.qp.get_unchecked_mut(map_position.0) = position;
}
position
}
fn up_heapify(&mut self, i: Position) {
let tmp = unsafe { *self.store.heap.get_unchecked(i.0) };
let pos = self.bubble_up(i, tmp);
self.heapify(pos)
}
pub(crate) fn heap_build(&mut self) {
if self.is_empty() {
return;
}
for i in (0..=parent(Position(self.len())).0).rev() {
self.heapify(Position(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 store = Store::from(vec);
let mut pq = PriorityQueue { store };
pq.heap_build();
pq
}
}
use crate::DoublePriorityQueue;
impl<I, P, H> From<DoublePriorityQueue<I, P, H>> for PriorityQueue<I, P, H>
where
I: Hash + Eq,
P: Ord,
H: BuildHasher,
{
fn from(pq: DoublePriorityQueue<I, P, H>) -> Self {
let store = pq.store;
let mut this = Self { store };
this.heap_build();
this
}
}
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 store = Store::from_iter(iter);
let mut pq = PriorityQueue { store };
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 = IntoIter<I, P>;
fn into_iter(self) -> IntoIter<I, P> {
self.store.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> {
self.store.iter()
}
}
impl<'a, I, P, H> IntoIterator for &'a mut PriorityQueue<I, P, H>
where
I: Hash + Eq,
P: Ord,
H: BuildHasher,
{
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 rebuild = if let Some(max) = max {
self.reserve(max);
better_to_rebuild(self.len(), max)
} else if min != 0 {
self.reserve(min);
better_to_rebuild(self.len(), min)
} else {
false
};
if rebuild {
self.store.extend(iter);
self.heap_build();
} else {
for (item, priority) in iter {
self.push(item, priority);
}
}
}
}
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.store == other.store
}
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
mod serde {
use core::cmp::{Eq, Ord};
use core::hash::{BuildHasher, Hash};
use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use super::PriorityQueue;
use crate::store::Store;
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,
{
self.store.serialize(serializer)
}
}
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>,
{
Store::deserialize(deserializer).map(|store| {
let mut pq = PriorityQueue { store };
pq.heap_build();
pq
})
}
}
}