diff --git a/src/core_iterators.rs b/src/core_iterators.rs index be9a68d..9a2f541 100644 --- a/src/core_iterators.rs +++ b/src/core_iterators.rs @@ -30,56 +30,97 @@ //! //! Usually you don't need to explicitly `use` any of the types declared here. +use core::iter::FusedIterator; + #[cfg(not(feature = "std"))] pub(crate) mod std { pub use ::alloc::vec; pub use core::*; } -use std::hash::Hash; +/// A draining iterator in arbitrary order over the couples +/// `(item, priority)` in the queue. +/// +/// It can be obtained calling the `drain` method. +pub struct Drain<'a, I: 'a, P: 'a> { + pub(crate) iter: ::indexmap::map::Drain<'a, I, P>, +} + +impl<'a, I: 'a, P: 'a> Iterator for Drain<'a, I, P> { + type Item = (I, P); + fn next(&mut self) -> Option<(I, P)> { + self.iter.next() + } +} + +impl<I, P> DoubleEndedIterator for Drain<'_, I, P> { + fn next_back(&mut self) -> Option<Self::Item> { + self.iter.next_back() + } +} + +impl<I, P> ExactSizeIterator for Drain<'_, I, P> { + fn len(&self) -> usize { + self.iter.len() + } +} + +impl<I, P> FusedIterator for Drain<'_, I, P> {} /// An iterator in arbitrary order over the couples /// `(item, priority)` in the queue. /// /// It can be obtained calling the `iter` method. -pub struct Iter<'a, I: 'a, P: 'a> -where - I: Hash + Eq, - P: Ord, -{ +pub struct Iter<'a, I: 'a, P: 'a> { pub(crate) iter: ::indexmap::map::Iter<'a, I, P>, } -impl<'a, I: 'a, P: 'a> Iterator for Iter<'a, I, P> -where - I: Hash + Eq, - P: Ord, -{ +impl<'a, I: 'a, P: 'a> Iterator for Iter<'a, I, P> { type Item = (&'a I, &'a P); fn next(&mut self) -> Option<(&'a I, &'a P)> { self.iter.next() } } +impl<I, P> DoubleEndedIterator for Iter<'_, I, P> { + fn next_back(&mut self) -> Option<Self::Item> { + self.iter.next_back() + } +} + +impl<I, P> ExactSizeIterator for Iter<'_, I, P> { + fn len(&self) -> usize { + self.iter.len() + } +} + +impl<I, P> FusedIterator for Iter<'_, I, P> {} + /// An iterator in arbitrary order over the couples /// `(item, priority)` that consumes the queue. /// /// It can be obtained calling the `into_iter` method from the `IntoIterator` trait. -pub struct IntoIter<I, P> -where - I: Hash + Eq, - P: Ord, -{ +pub struct IntoIter<I, P> { pub(crate) iter: ::indexmap::map::IntoIter<I, P>, } -impl<I, P> Iterator for IntoIter<I, P> -where - I: Hash + Eq, - P: Ord, -{ +impl<I, P> Iterator for IntoIter<I, P> { type Item = (I, P); fn next(&mut self) -> Option<(I, P)> { self.iter.next() } } + +impl<I, P> DoubleEndedIterator for IntoIter<I, P> { + fn next_back(&mut self) -> Option<Self::Item> { + self.iter.next_back() + } +} + +impl<I, P> ExactSizeIterator for IntoIter<I, P> { + fn len(&self) -> usize { + self.iter.len() + } +} + +impl<I, P> FusedIterator for IntoIter<I, P> {} diff --git a/src/double_priority_queue/iterators.rs b/src/double_priority_queue/iterators.rs index d27e577..7c29ba6 100644 --- a/src/double_priority_queue/iterators.rs +++ b/src/double_priority_queue/iterators.rs @@ -36,10 +36,9 @@ pub(crate) mod std { } use core::hash::BuildHasher; -use std::cmp::{Eq, Ord}; +use std::cmp::Ord; #[cfg(feature = "std")] use std::collections::hash_map::RandomState; -use std::hash::Hash; use std::iter::*; use crate::DoublePriorityQueue; @@ -58,7 +57,6 @@ use crate::DoublePriorityQueue; #[cfg(feature = "std")] pub struct IterMut<'a, I: 'a, P: 'a, H: 'a = RandomState> where - I: Hash + Eq, P: Ord, { pq: &'a mut DoublePriorityQueue<I, P, H>, @@ -68,7 +66,6 @@ where #[cfg(not(feature = "std"))] pub struct IterMut<'a, I: 'a, P: 'a, H: 'a> where - I: Hash + Eq, P: Ord, { pq: &'a mut DoublePriorityQueue<I, P, H>, @@ -77,7 +74,6 @@ where impl<'a, I: 'a, P: 'a, H: 'a> IterMut<'a, I, P, H> where - I: Hash + Eq, P: Ord, { pub(crate) fn new(pq: &'a mut DoublePriorityQueue<I, P, H>) -> Self { @@ -87,7 +83,6 @@ where impl<'a, 'b: 'a, I: 'a, P: 'a, H: 'a> Iterator for IterMut<'a, I, P, H> where - I: Hash + Eq, P: Ord, H: BuildHasher, { @@ -106,9 +101,44 @@ where } } +impl<'a, 'b: 'a, I: 'a, P: 'a, H: 'a> DoubleEndedIterator for IterMut<'a, I, P, H> +where + P: Ord, + H: BuildHasher, +{ + fn next_back(&mut self) -> Option<Self::Item> { + use indexmap::map::MutableKeys; + let r: Option<(&'a mut I, &'a mut P)> = self + .pq + .store + .map + .get_index_mut2(self.pos) + .map(|(i, p)| (i as *mut I, p as *mut P)) + .map(|(i, p)| unsafe { (i.as_mut().unwrap(), p.as_mut().unwrap()) }); + self.pos -= 1; + r + } +} + +impl<'a, I, P, H> ExactSizeIterator for IterMut<'_, I, P, H> +where + P: Ord, + H: BuildHasher, +{ + fn len(&self) -> usize { + self.pq.len() + } +} + +impl<'a, I, P, H> FusedIterator for IterMut<'_, I, P, H> +where + P: Ord, + H: BuildHasher, +{ +} + impl<'a, I: 'a, P: 'a, H: 'a> Drop for IterMut<'a, I, P, H> where - I: Hash + Eq, P: Ord, { fn drop(&mut self) { @@ -127,7 +157,6 @@ where #[cfg(feature = "std")] pub struct IntoSortedIter<I, P, H = RandomState> where - I: Hash + Eq, P: Ord, { pub(crate) pq: DoublePriorityQueue<I, P, H>, @@ -136,7 +165,6 @@ where #[cfg(not(feature = "std"))] pub struct IntoSortedIter<I, P, H> where - I: Hash + Eq, P: Ord, { pub(crate) pq: DoublePriorityQueue<I, P, H>, @@ -144,7 +172,6 @@ where impl<I, P, H> Iterator for IntoSortedIter<I, P, H> where - I: Hash + Eq, P: Ord, { type Item = (I, P); @@ -155,10 +182,20 @@ where impl<I, P, H> DoubleEndedIterator for IntoSortedIter<I, P, H> where - I: Hash + Eq, P: Ord, { fn next_back(&mut self) -> Option<(I, P)> { self.pq.pop_max() } } + +impl<I, P, H> ExactSizeIterator for IntoSortedIter<I, P, H> +where + P: Ord, +{ + fn len(&self) -> usize { + self.pq.len() + } +} + +impl<I, P, H> FusedIterator for IntoSortedIter<I, P, H> where P: Ord {} diff --git a/src/double_priority_queue/mod.rs b/src/double_priority_queue/mod.rs index dd09f91..e83b3fd 100644 --- a/src/double_priority_queue/mod.rs +++ b/src/double_priority_queue/mod.rs @@ -34,7 +34,7 @@ pub mod iterators; #[cfg(not(feature = "std"))] use std::vec::Vec; -use crate::core_iterators::{IntoIter, Iter}; +use crate::core_iterators::*; use crate::store::{Index, Position, Store}; use iterators::*; @@ -88,21 +88,13 @@ use std::mem::replace; /// ``` #[derive(Clone)] #[cfg(feature = "std")] -pub struct DoublePriorityQueue<I, P, H = RandomState> -where - I: Hash + Eq, - P: Ord, -{ +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> -where - I: Hash + Eq, - P: Ord, -{ +pub struct DoublePriorityQueue<I, P, H> { pub(crate) store: Store<I, P, H>, } @@ -181,6 +173,17 @@ where store: Store::with_capacity_and_hasher(capacity, hash_builder), } } +} + +impl<I, P, H> DoublePriorityQueue<I, P, H> { + /// Returns the number of elements the internal map can hold without + /// reallocating. + /// + /// This number is a lower bound; the map might be able to hold more, + /// but is guaranteed to be able to hold at least this many. + pub fn capacity(&self) -> usize { + self.store.capacity() + } /// Returns an iterator in arbitrary order over the /// (item, priority) elements in the queue @@ -188,17 +191,59 @@ where self.store.iter() } + /// Clears the PriorityQueue, returning an iterator over the removed elements in arbitrary order. + /// If the iterator is dropped before being fully consumed, it drops the remaining elements in arbitrary order. + pub fn drain(&mut self) -> Drain<I, P> { + self.store.drain() + } + /// Shrinks the capacity of the internal data structures /// that support this operation as much as possible. pub fn shrink_to_fit(&mut self) { self.store.shrink_to_fit(); } -} + /// Returns the number of elements in the priority queue. + #[inline] + pub fn len(&self) -> usize { + self.store.len() + } + + /// Returns true if the priority queue contains no elements. + pub fn is_empty(&self) -> bool { + self.store.is_empty() + } + + /// Returns the couple (item, priority) with the lowest + /// priority in the queue, or None if it is empty. + /// + /// Computes in **O(1)** time + 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) + }) + } + + // reserve_exact -> IndexMap does not implement reserve_exact + + /// Reserves capacity for at least `additional` more elements to be inserted + /// in the given `DoublePriorityQueue`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + pub fn reserve(&mut self, additional: usize) { + self.store.reserve(additional); + } +} impl<I, P, H> DoublePriorityQueue<I, P, H> where P: Ord, - I: Hash + Eq, { /// Return an iterator in arbitrary order over the /// (item, priority) elements in the queue. @@ -214,18 +259,6 @@ where IterMut::new(self) } - /// Returns the couple (item, priority) with the lowest - /// priority in the queue, or None if it is empty. - /// - /// Computes in **O(1)** time - 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) - }) - } - /// Returns the couple (item, priority) with the greatest /// priority in the queue, or None if it is empty. /// @@ -238,15 +271,6 @@ where }) } - /// Returns the number of elements the internal map can hold without - /// reallocating. - /// - /// This number is a lower bound; the map might be able to hold more, - /// but is guaranteed to be able to hold at least this many. - pub fn capacity(&self) -> usize { - self.store.capacity() - } - /// Removes the item with the lowest priority from /// the priority queue and returns the pair (item, priority), /// or None if the queue is empty. @@ -295,17 +319,6 @@ where res } - /// Returns the number of elements in the priority queue. - #[inline] - pub fn len(&self) -> usize { - self.store.len() - } - - /// Returns true if the priority queue contains no elements. - pub fn is_empty(&self) -> bool { - self.store.is_empty() - } - /// Generates a new double ended iterator from self that /// will extract the elements from the one with the lowest priority /// to the highest one. @@ -316,25 +329,66 @@ where impl<I, P, H> DoublePriorityQueue<I, P, H> where - P: Ord, - I: Hash + Eq, H: BuildHasher, { - // reserve_exact -> IndexMap does not implement reserve_exact + /// Returns the couple (item, priority) with the lowest + /// priority in the queue, or None if it is empty. + /// + /// The item is a mutable reference, but it's a logic error to modify it + /// in a way that change the result of `Hash` or `Eq`. + /// + /// The priority cannot be modified with a call to this function. + /// To modify the priority use `push`, `change_priority` or + /// `change_priority_by`. + /// + /// Computes in **O(1)** time + pub fn peek_min_mut(&mut self) -> Option<(&mut I, &P)> { + use indexmap::map::MutableKeys; - /// Reserves capacity for at least `additional` more elements to be inserted - /// in the given `DoublePriorityQueue`. The collection may reserve more space to avoid - /// frequent reallocations. After calling `reserve`, capacity will be - /// greater than or equal to `self.len() + additional`. Does nothing if - /// capacity is already sufficient. + 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, +{ + /// Returns the couple (item, priority) with the greatest + /// priority in the queue, or None if it is empty. /// - /// # Panics + /// The item is a mutable reference, but it's a logic error to modify it + /// in a way that change the result of `Hash` or `Eq`. /// - /// Panics if the new capacity overflows `usize`. - pub fn reserve(&mut self, additional: usize) { - self.store.reserve(additional); + /// The priority cannot be modified with a call to this function. + /// To modify the priority use `push`, `change_priority` or + /// `change_priority_by`. + /// + /// Computes in **O(1)** time + 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, +{ /// Insert the item-priority pair into the queue. /// /// If an element equal to `item` was already into the queue, @@ -437,51 +491,6 @@ where }) } - /// Returns the couple (item, priority) with the lowest - /// priority in the queue, or None if it is empty. - /// - /// The item is a mutable reference, but it's a logic error to modify it - /// in a way that change the result of `Hash` or `Eq`. - /// - /// The priority cannot be modified with a call to this function. - /// To modify the priority use `push`, `change_priority` or - /// `change_priority_by`. - /// - /// Computes in **O(1)** time - 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)) - } - - /// Returns the couple (item, priority) with the greatest - /// priority in the queue, or None if it is empty. - /// - /// The item is a mutable reference, but it's a logic error to modify it - /// in a way that change the result of `Hash` or `Eq`. - /// - /// The priority cannot be modified with a call to this function. - /// To modify the priority use `push`, `change_priority` or - /// `change_priority_by`. - /// - /// Computes in **O(1)** time - 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)) - } - /// Change the priority of an Item using the provided function. /// Return a boolean value where `true` means the item was in the queue and update was successful /// @@ -582,17 +591,19 @@ where } } -impl<I, P, H> DoublePriorityQueue<I, P, H> -where - P: Ord, - I: Hash + Eq, -{ +impl<I, P, H> DoublePriorityQueue<I, P, H> { + /// Returns the index of the min element + 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, - I: Hash + Eq, { /**************************************************************************/ /* internal functions */ @@ -805,14 +816,6 @@ where ), } } - - /// Returns the index of the min element - fn find_min(&self) -> Option<Position> { - match self.len() { - 0 => None, - _ => Some(Position(0)), - } - } } //FIXME: fails when the vector contains repeated items diff --git a/src/priority_queue/iterators.rs b/src/priority_queue/iterators.rs index e2d1c0b..30f5f08 100644 --- a/src/priority_queue/iterators.rs +++ b/src/priority_queue/iterators.rs @@ -36,10 +36,9 @@ pub(crate) mod std { } use core::hash::BuildHasher; -use std::cmp::{Eq, Ord}; +use std::cmp::Ord; #[cfg(feature = "std")] use std::collections::hash_map::RandomState; -use std::hash::Hash; use std::iter::*; use crate::PriorityQueue; @@ -58,7 +57,6 @@ use crate::PriorityQueue; #[cfg(feature = "std")] pub struct IterMut<'a, I: 'a, P: 'a, H: 'a = RandomState> where - I: Hash + Eq, P: Ord, { pq: &'a mut PriorityQueue<I, P, H>, @@ -68,7 +66,6 @@ where #[cfg(not(feature = "std"))] pub struct IterMut<'a, I: 'a, P: 'a, H: 'a> where - I: Hash + Eq, P: Ord, { pq: &'a mut PriorityQueue<I, P, H>, @@ -77,7 +74,6 @@ where impl<'a, I: 'a, P: 'a, H: 'a> IterMut<'a, I, P, H> where - I: Hash + Eq, P: Ord, { pub(crate) fn new(pq: &'a mut PriorityQueue<I, P, H>) -> Self { @@ -87,7 +83,6 @@ where impl<'a, 'b: 'a, I: 'a, P: 'a, H: 'a> Iterator for IterMut<'a, I, P, H> where - I: Hash + Eq, P: Ord, H: BuildHasher, { @@ -109,7 +104,6 @@ where impl<'a, I: 'a, P: 'a, H: 'a> Drop for IterMut<'a, I, P, H> where - I: Hash + Eq, P: Ord, { fn drop(&mut self) { @@ -122,26 +116,17 @@ where /// /// It can be obtained calling the `into_sorted_iter` method. #[cfg(feature = "std")] -pub struct IntoSortedIter<I, P, H = RandomState> -where - I: Hash + Eq, - P: Ord, -{ +pub struct IntoSortedIter<I, P, H = RandomState> { pub(crate) pq: PriorityQueue<I, P, H>, } #[cfg(not(feature = "std"))] -pub struct IntoSortedIter<I, P, H> -where - I: Hash + Eq, - P: Ord, -{ +pub struct IntoSortedIter<I, P, H> { pub(crate) pq: PriorityQueue<I, P, H>, } impl<I, P, H> Iterator for IntoSortedIter<I, P, H> where - I: Hash + Eq, P: Ord, { type Item = (I, P); diff --git a/src/priority_queue/mod.rs b/src/priority_queue/mod.rs index 70ac22c..a9f351d 100644 --- a/src/priority_queue/mod.rs +++ b/src/priority_queue/mod.rs @@ -35,7 +35,7 @@ pub mod iterators; #[cfg(not(feature = "std"))] use std::vec::Vec; -use crate::core_iterators::{IntoIter, Iter}; +use crate::core_iterators::*; use crate::store::{Index, Position, Store}; use iterators::*; @@ -79,21 +79,13 @@ use std::mem::replace; /// ``` #[derive(Clone, Debug)] #[cfg(feature = "std")] -pub struct PriorityQueue<I, P, H = RandomState> -where - I: Hash + Eq, - P: Ord, -{ +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> -where - I: Hash + Eq, - P: Ord, -{ +pub struct PriorityQueue<I, P, H> { pub(crate) store: Store<I, P, H>, } @@ -172,7 +164,9 @@ where store: Store::with_capacity_and_hasher(capacity, hash_builder), } } +} +impl<I, P, H> PriorityQueue<I, P, H> { /// Returns an iterator in arbitrary order over the /// (item, priority) elements in the queue pub fn iter(&self) -> Iter<I, P> { @@ -184,25 +178,11 @@ where pub fn shrink_to_fit(&mut self) { self.store.shrink_to_fit(); } -} -impl<I, P, H> PriorityQueue<I, P, H> -where - P: Ord, - I: Hash + Eq, -{ - /// Returns an iterator in arbitrary order over the - /// (item, priority) elements in the queue. - /// - /// The item and the priority are mutable references, but it's a logic error - /// to modify the item in a way that change the result of `Hash` or `Eq`. - /// - /// It's *not* an error, instead, to modify the priorities, because the heap - /// will be rebuilt once the `IterMut` goes out of scope. It would be - /// rebuilt even if no priority value would have been modified, but the - /// procedure will not move anything, but just compare the priorities. - pub fn iter_mut(&mut self) -> IterMut<I, P, H> { - IterMut::new(self) + /// Clears the PriorityQueue, returning an iterator over the removed elements in arbitrary order. + /// If the iterator is dropped before being fully consumed, it drops the remaining elements in arbitrary order. + pub fn drain(&mut self) -> Drain<I, P> { + self.store.drain() } /// Returns the couple (item, priority) with the greatest @@ -225,6 +205,59 @@ where self.store.capacity() } + /// Returns the number of elements in the priority queue. + #[inline] + pub fn len(&self) -> usize { + self.store.len() + } + + /// Returns true if the priority queue contains no elements. + pub fn is_empty(&self) -> bool { + self.store.is_empty() + } + + /// Returns the items not ordered + pub fn into_vec(self) -> Vec<I> { + self.store.into_vec() + } + + /// Drops all items from the priority queue + pub fn clear(&mut self) { + self.store.clear(); + } + + /// Reserves capacity for at least `additional` more elements to be inserted + /// in the given `PriorityQueue`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + pub fn reserve(&mut self, additional: usize) { + self.store.reserve(additional); + } +} + +impl<I, P, H> PriorityQueue<I, P, H> +where + P: Ord, +{ + /// Returns an iterator in arbitrary order over the + /// (item, priority) elements in the queue. + /// + /// The item and the priority are mutable references, but it's a logic error + /// to modify the item in a way that change the result of `Hash` or `Eq`. + /// + /// It's *not* an error, instead, to modify the priorities, because the heap + /// will be rebuilt once the `IterMut` goes out of scope. It would be + /// rebuilt even if no priority value would have been modified, but the + /// procedure will not move anything, but just compare the priorities. + pub fn iter_mut(&mut self) -> IterMut<I, P, H> { + IterMut::new(self) + } + /// Removes the item with the greatest priority from /// the priority queue and returns the pair (item, priority), /// or None if the queue is empty. @@ -251,17 +284,6 @@ where res } - /// Returns the number of elements in the priority queue. - #[inline] - pub fn len(&self) -> usize { - self.store.len() - } - - /// Returns true if the priority queue contains no elements. - pub fn is_empty(&self) -> bool { - self.store.is_empty() - } - /// Generates a new iterator from self that /// will extract the elements from the one with the highest priority /// to the lowest one. @@ -278,19 +300,6 @@ where { // reserve_exact -> IndexMap does not implement reserve_exact - /// Reserves capacity for at least `additional` more elements to be inserted - /// in the given `PriorityQueue`. The collection may reserve more space to avoid - /// frequent reallocations. After calling `reserve`, capacity will be - /// greater than or equal to `self.len() + additional`. Does nothing if - /// capacity is already sufficient. - /// - /// # Panics - /// - /// Panics if the new capacity overflows `usize`. - pub fn reserve(&mut self, additional: usize) { - self.store.reserve(additional); - } - /// Insert the item-priority pair into the queue. /// /// If an element equal to `item` was already into the queue, @@ -491,16 +500,6 @@ where }) } - /// Returns the items not ordered - pub fn into_vec(self) -> Vec<I> { - self.store.into_vec() - } - - /// Drops all items from the priority queue - pub fn clear(&mut self) { - self.store.clear(); - } - /// Move all items of the `other` queue to `self` /// ignoring the items Eq to elements already in `self` /// At the end, `other` will be empty. @@ -524,7 +523,6 @@ where impl<I, P, H> PriorityQueue<I, P, H> where P: Ord, - I: Hash + Eq, { /**************************************************************************/ /* internal functions */ diff --git a/src/store.rs b/src/store.rs index 9b6ae5a..7391f72 100644 --- a/src/store.rs +++ b/src/store.rs @@ -52,11 +52,7 @@ pub(crate) struct Position(pub usize); /// Internal storage of PriorityQueue and DoublePriorityQueue #[derive(Clone)] #[cfg(feature = "std")] -pub(crate) struct Store<I, P, H = RandomState> -where - I: Hash + Eq, - P: Ord, -{ +pub(crate) struct Store<I, P, H = RandomState> { pub map: IndexMap<I, P, H>, // Stores the items and assign them an index pub heap: Vec<Index>, // Implements the heap of indexes pub qp: Vec<Position>, // Performs the translation from the index @@ -66,11 +62,7 @@ where #[derive(Clone)] #[cfg(not(feature = "std"))] -pub(crate) struct Store<I, P, H> -where - I: Hash + Eq, - P: Ord, -{ +pub(crate) struct Store<I, P, H> { pub map: IndexMap<I, P, H>, // Stores the items and assign them an index pub heap: Vec<Index>, // Implements the heap of indexes pub qp: Vec<Position>, // Performs the translation from the index @@ -139,7 +131,9 @@ where size: 0, } } +} +impl<I, P, H> Store<I, P, H> { /// Returns an iterator in arbitrary order over the /// (item, priority) elements in the queue pub fn iter(&self) -> Iter<I, P> { @@ -172,13 +166,19 @@ where self.heap.reserve(additional); self.qp.reserve(additional); } -} -impl<I, P, H> Store<I, P, H> -where - P: Ord, - I: Hash + Eq, -{ + /// Clears the store, returning an iterator over the removed elements in arbitrary order. + /// If the iterator is dropped before being fully consumed, it drops the remaining elements in arbitrary order. + pub fn drain(&mut self) -> Drain<'_, I, P> { + self.heap.clear(); + self.qp.clear(); + self.size = 0; + + Drain { + iter: self.map.drain(..), + } + } + /// Returns the number of elements the internal map can hold without /// reallocating. /// @@ -201,6 +201,19 @@ where self.size == 0 } + /// Returns the items not ordered + pub fn into_vec(self) -> Vec<I> { + self.map.into_iter().map(|(i, _)| i).collect() + } + + /// Drops all items from the priority queue + pub fn clear(&mut self) { + self.heap.clear(); + self.qp.clear(); + self.map.clear(); + self.size = 0; + } + /// Swap two elements keeping a consistent state. /// /// Computes in **O(1)** time @@ -378,19 +391,6 @@ where }) } - /// Returns the items not ordered - pub fn into_vec(self) -> Vec<I> { - self.map.into_iter().map(|(i, _)| i).collect() - } - - /// Drops all items from the priority queue - pub fn clear(&mut self) { - self.heap.clear(); - self.qp.clear(); - self.map.clear(); - self.size = 0; - } - /// Move all items of the `other` queue to `self` /// ignoring the items Eq to elements already in `self` /// At the end, `other` will be empty. @@ -405,10 +405,9 @@ where if other.size == 0 { return; } - let drain = other.map.drain(..); // what should we do for duplicated keys? // ignore - for (k, v) in drain { + for (k, v) in other.drain() { if !self.map.contains_key(&k) { let i = self.size; self.map.insert(k, v); @@ -417,16 +416,10 @@ where self.size += 1; } } - other.clear(); } } -impl<I, P, H> IntoIterator for Store<I, P, H> -where - I: Hash + Eq, - P: Ord, - H: BuildHasher, -{ +impl<I, P, H> IntoIterator for Store<I, P, H> { type Item = (I, P); type IntoIter = IntoIter<I, P>; fn into_iter(self) -> IntoIter<I, P> { @@ -436,12 +429,7 @@ where } } -impl<'a, I, P, H> IntoIterator for &'a Store<I, P, H> -where - I: Hash + Eq, - P: Ord, - H: BuildHasher, -{ +impl<'a, I, P, H> IntoIterator for &'a Store<I, P, H> { type Item = (&'a I, &'a P); type IntoIter = Iter<'a, I, P>; fn into_iter(self) -> Iter<'a, I, P> { @@ -550,8 +538,8 @@ where use std::fmt; impl<I, P, H> fmt::Debug for Store<I, P, H> where - I: fmt::Debug + Hash + Eq, - P: fmt::Debug + Ord, + I: fmt::Debug, + P: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_map() @@ -575,12 +563,7 @@ mod serde { use serde::ser::{Serialize, SerializeSeq, Serializer}; - impl<I, P, H> Serialize for Store<I, P, H> - where - I: Hash + Eq + Serialize, - P: Ord + Serialize, - H: BuildHasher, - { + impl<I, P, H> Serialize for Store<I, P, H> { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer, diff --git a/tests/double_priority_queue.rs b/tests/double_priority_queue.rs index 4d3b280..149de1e 100644 --- a/tests/double_priority_queue.rs +++ b/tests/double_priority_queue.rs @@ -343,6 +343,24 @@ mod doublepq_tests { } } + #[test] + fn drain() { + use std::collections::hash_map::RandomState; + let mut queue = DoublePriorityQueue::<i32, i32, RandomState>::default(); + + for i in 0..7 { + queue.push(i, i); + } + + let previous_capacity = queue.capacity(); + queue.drain(); + + assert_eq!(queue.len(), 0); + assert_eq!(queue.capacity(), previous_capacity); + assert_eq!(queue.pop_min(), None); + assert_eq!(queue.pop_max(), None); + } + #[test] fn extend() { let mut pq = DoublePriorityQueue::new(); diff --git a/tests/priority_queue.rs b/tests/priority_queue.rs index 9acf62d..127591f 100644 --- a/tests/priority_queue.rs +++ b/tests/priority_queue.rs @@ -327,6 +327,23 @@ mod pqueue_tests { } } + #[test] + fn drain() { + use std::collections::hash_map::RandomState; + let mut queue = PriorityQueue::<i32, i32, RandomState>::default(); + + for i in 0..7 { + queue.push(i, i); + } + + let previous_capacity = queue.capacity(); + queue.drain(); + + assert_eq!(queue.len(), 0); + assert_eq!(queue.capacity(), previous_capacity); + assert_eq!(queue.pop(), None); + } + #[test] fn extend() { let mut pq = PriorityQueue::new();