pub mod iterators;
#[cfg(not(feature = "std"))]
use std::vec::Vec;
use crate::better_to_rebuild;
use crate::core_iterators::*;
use crate::store::{left, level, 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)]
#[cfg(feature = "std")]
pub struct DoublePriorityQueue<I, P, H = RandomState> {
pub(crate) store: Store<I, P, H>,
}
#[derive(Clone)]
#[cfg(not(feature = "std"))]
pub struct DoublePriorityQueue<I, P, H> {
pub(crate) store: Store<I, P, H>,
}
impl<I, P, H> Eq for DoublePriorityQueue<I, P, H>
where
I: Hash + Eq,
P: Ord,
H: BuildHasher,
{
}
impl<I, P, H> Default for DoublePriorityQueue<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> DoublePriorityQueue<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> DoublePriorityQueue<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> DoublePriorityQueue<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> DoublePriorityQueue<I, P, H> {
pub fn capacity(&self) -> usize {
self.store.capacity()
}
pub fn iter(&self) -> Iter<'_, I, P> {
self.store.iter()
}
pub fn drain(&mut self) -> Drain<'_, I, P> {
self.store.drain()
}
pub fn shrink_to_fit(&mut self) {
self.store.shrink_to_fit();
}
#[inline]
pub fn len(&self) -> usize {
self.store.len()
}
pub fn is_empty(&self) -> bool {
self.store.is_empty()
}
pub fn peek_min(&self) -> Option<(&I, &P)> {
self.find_min().and_then(|i| {
self.store
.map
.get_index(unsafe { *self.store.heap.get_unchecked(i.0) }.0)
})
}
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> DoublePriorityQueue<I, P, H>
where
P: Ord,
{
pub fn iter_mut(&mut self) -> IterMut<'_, I, P, H> {
IterMut::new(self)
}
pub fn peek_max(&self) -> Option<(&I, &P)> {
self.find_max().and_then(|i| {
self.store
.map
.get_index(unsafe { *self.store.heap.get_unchecked(i.0) }.0)
})
}
pub fn pop_min(&mut self) -> Option<(I, P)> {
self.find_min().and_then(|i| {
let r = self.store.swap_remove(i);
self.heapify(i);
r
})
}
pub fn pop_max(&mut self) -> Option<(I, P)> {
self.find_max().and_then(|i| {
let r = self.store.swap_remove(i);
self.heapify(i);
r
})
}
pub fn into_ascending_sorted_vec(mut self) -> Vec<I> {
let mut res = Vec::with_capacity(self.store.size);
while let Some((i, _)) = self.pop_min() {
res.push(i);
}
res
}
pub fn into_descending_sorted_vec(mut self) -> Vec<I> {
let mut res = Vec::with_capacity(self.store.size);
while let Some((i, _)) = self.pop_max() {
res.push(i);
}
res
}
pub fn into_sorted_iter(self) -> IntoSortedIter<I, P, H> {
IntoSortedIter { pq: self }
}
}
impl<I, P, H> DoublePriorityQueue<I, P, H>
where
H: BuildHasher,
{
pub fn peek_min_mut(&mut self) -> Option<(&mut I, &P)> {
use indexmap::map::MutableKeys;
self.find_min()
.and_then(move |i| {
self.store
.map
.get_index_mut2(unsafe { *self.store.heap.get_unchecked(i.0) }.0)
})
.map(|(k, v)| (k, &*v))
}
}
impl<I, P, H> DoublePriorityQueue<I, P, H>
where
P: Ord,
H: BuildHasher,
{
pub fn peek_max_mut(&mut self) -> Option<(&mut I, &P)> {
use indexmap::map::MutableKeys;
self.find_max()
.and_then(move |i| {
self.store
.map
.get_index_mut2(unsafe { *self.store.heap.get_unchecked(i.0) }.0)
})
.map(|(k, v)| (k, &*v))
}
}
impl<I, P, H> DoublePriorityQueue<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_min_if<F>(&mut self, f: F) -> Option<(I, P)>
where
F: FnOnce(&mut I, &mut P) -> bool,
{
self.find_min().and_then(|i| {
let r = self.store.swap_remove_if(i, f);
self.heapify(i);
r
})
}
pub fn pop_max_if<F>(&mut self, f: F) -> Option<(I, P)>
where
F: FnOnce(&mut I, &mut P) -> bool,
{
self.find_max().and_then(|i| {
let r = self.store.swap_remove_if(i, f);
self.up_heapify(i);
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 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 into_vec(self) -> Vec<I> {
self.store.into_vec()
}
pub fn clear(&mut self) {
self.store.clear();
}
pub fn append(&mut self, other: &mut Self) {
self.store.append(&mut other.store);
self.heap_build();
}
}
impl<I, P, H> DoublePriorityQueue<I, P, H> {
fn find_min(&self) -> Option<Position> {
match self.len() {
0 => None,
_ => Some(Position(0)),
}
}
}
impl<I, P, H> DoublePriorityQueue<I, P, H>
where
P: Ord,
{
fn heapify(&mut self, i: Position) {
if self.len() <= 1 {
return;
}
if level(i) % 2 == 0 {
self.heapify_min(i)
} else {
self.heapify_max(i)
}
}
fn heapify_min(&mut self, mut i: Position) {
while i <= parent(Position(self.len() - 1)) {
let m = i;
let l = left(i);
let r = right(i);
i = *[l, r, left(l), right(l), left(r), right(r)]
.iter()
.map_while(|i| self.store.heap.get(i.0).map(|index| (i, index)))
.min_by_key(|(_, index)| {
self.store
.map
.get_index(index.0)
.map(|(_, priority)| priority)
.unwrap()
})
.unwrap()
.0;
if unsafe {
self.store.get_priority_from_position(i) < self.store.get_priority_from_position(m)
} {
self.store.swap(i, m);
if i > r {
let p = parent(i);
if unsafe {
self.store.get_priority_from_position(i)
> self.store.get_priority_from_position(p)
} {
self.store.swap(i, p);
}
} else {
break;
}
} else {
break;
}
}
}
fn heapify_max(&mut self, mut i: Position) {
while i <= parent(Position(self.len() - 1)) {
let m = i;
let l = left(i);
let r = right(i);
i = *[l, r, left(l), right(l), left(r), right(r)]
.iter()
.map_while(|i| self.store.heap.get(i.0).map(|index| (i, index)))
.max_by_key(|(_, index)| {
self.store
.map
.get_index(index.0)
.map(|(_, priority)| priority)
.unwrap()
})
.unwrap()
.0;
if unsafe {
self.store.get_priority_from_position(i) > self.store.get_priority_from_position(m)
} {
self.store.swap(i, m);
if i > r {
let p = parent(i);
if unsafe {
self.store.get_priority_from_position(i)
< self.store.get_priority_from_position(p)
} {
self.store.swap(i, p);
}
} else {
break;
}
} else {
break;
}
}
}
fn bubble_up(&mut self, mut position: Position, map_position: Index) -> Position {
let priority = self.store.map.get_index(map_position.0).unwrap().1;
if position.0 > 0 {
let parent = parent(position);
let parent_priority = unsafe { self.store.get_priority_from_position(parent) };
let parent_index = unsafe { *self.store.heap.get_unchecked(parent.0) };
position = match (level(position) % 2 == 0, parent_priority < priority) {
(true, true) => {
unsafe {
*self.store.heap.get_unchecked_mut(position.0) = parent_index;
*self.store.qp.get_unchecked_mut(parent_index.0) = position;
}
self.bubble_up_max(parent, map_position)
}
(true, false) => self.bubble_up_min(position, map_position),
(false, true) => self.bubble_up_max(position, map_position),
(false, false) => {
unsafe {
*self.store.heap.get_unchecked_mut(position.0) = parent_index;
*self.store.qp.get_unchecked_mut(parent_index.0) = position;
}
self.bubble_up_min(parent, map_position)
}
}
}
unsafe {
*self.store.heap.get_unchecked_mut(position.0) = map_position;
*self.store.qp.get_unchecked_mut(map_position.0) = position;
}
position
}
fn bubble_up_min(&mut self, mut position: Position, map_position: Index) -> Position {
let priority = self.store.map.get_index(map_position.0).unwrap().1;
let mut grand_parent = Position(0);
while if position.0 > 0 && parent(position).0 > 0 {
grand_parent = parent(parent(position));
(unsafe { self.store.get_priority_from_position(grand_parent) }) > priority
} else {
false
} {
unsafe {
let grand_parent_index = *self.store.heap.get_unchecked(grand_parent.0);
*self.store.heap.get_unchecked_mut(position.0) = grand_parent_index;
*self.store.qp.get_unchecked_mut(grand_parent_index.0) = position;
}
position = grand_parent;
}
position
}
fn bubble_up_max(&mut self, mut position: Position, map_position: Index) -> Position {
let priority = self.store.map.get_index(map_position.0).unwrap().1;
let mut grand_parent = Position(0);
while if position.0 > 0 && parent(position).0 > 0 {
grand_parent = parent(parent(position));
(unsafe { self.store.get_priority_from_position(grand_parent) }) < priority
} else {
false
} {
unsafe {
let grand_parent_index = *self.store.heap.get_unchecked(grand_parent.0);
*self.store.heap.get_unchecked_mut(position.0) = grand_parent_index;
*self.store.qp.get_unchecked_mut(grand_parent_index.0) = position;
}
position = grand_parent;
}
position
}
fn up_heapify(&mut self, i: Position) {
if let Some(&tmp) = self.store.heap.get(i.0) {
let pos = self.bubble_up(i, tmp);
if i != pos {
self.heapify(i)
}
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));
}
}
fn find_max(&self) -> Option<Position> {
match self.len() {
0 => None,
1 => Some(Position(0)),
2 => Some(Position(1)),
_ => Some(
*[Position(1), Position(2)]
.iter()
.max_by_key(|i| unsafe { self.store.get_priority_from_position(**i) })
.unwrap(),
),
}
}
}
impl<I, P, H> From<Vec<(I, P)>> for DoublePriorityQueue<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 = DoublePriorityQueue { store };
pq.heap_build();
pq
}
}
use crate::PriorityQueue;
impl<I, P, H> From<PriorityQueue<I, P, H>> for DoublePriorityQueue<I, P, H>
where
I: Hash + Eq,
P: Ord,
H: BuildHasher,
{
fn from(pq: PriorityQueue<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 DoublePriorityQueue<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 = DoublePriorityQueue { store };
pq.heap_build();
pq
}
}
impl<I, P, H> IntoIterator for DoublePriorityQueue<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 DoublePriorityQueue<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 DoublePriorityQueue<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 DoublePriorityQueue<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::fmt;
impl<I, P, H> fmt::Debug for DoublePriorityQueue<I, P, H>
where
I: Hash + Eq + fmt::Debug,
P: Ord + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
self.store.fmt(f)
}
}
use std::cmp::PartialEq;
impl<I, P1, H1, P2, H2> PartialEq<DoublePriorityQueue<I, P2, H2>> for DoublePriorityQueue<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: &DoublePriorityQueue<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::DoublePriorityQueue;
use crate::store::Store;
impl<I, P, H> Serialize for DoublePriorityQueue<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 DoublePriorityQueue<I, P, H>
where
I: Hash + Eq + Deserialize<'de>,
P: Ord + Deserialize<'de>,
H: BuildHasher + Default,
{
fn deserialize<D>(deserializer: D) -> Result<DoublePriorityQueue<I, P, H>, D::Error>
where
D: Deserializer<'de>,
{
Store::deserialize(deserializer).map(|store| {
let mut pq = DoublePriorityQueue { store };
pq.heap_build();
pq
})
}
}
}