pub struct KeyedPriorityQueue<TKey, TPriority, S = RandomState>{ /* private fields */ }
Expand description
A priority queue that support lookup by key.
Bigger TPriority
values will have more priority.
It is logic error if priority values changes other way than by set_priority
method.
It is logic error if key values changes somehow while in queue.
This changes normally possible only through Cell
, RefCell
, global state, IO, or unsafe code.
If you feel KeyedPriorityQueue slow, it can be because it uses RandomState (relatably slow but strong against HashDoS attack) hasher by default. You can try fnv or fxhash crates hashers.
§Examples
§Main example
use keyed_priority_queue::KeyedPriorityQueue;
let mut queue = KeyedPriorityQueue::new();
// Currently queue is empty
assert_eq!(queue.peek(), None);
queue.push("Second", 4);
queue.push("Third", 3);
queue.push("First", 5);
queue.push("Fourth", 2);
queue.push("Fifth", 1);
// Peek return references to most important pair.
assert_eq!(queue.peek(), Some((&"First", &5)));
assert_eq!(queue.len(), 5);
// We can clone queue if both key and priority is clonable
let mut queue_clone = queue.clone();
// We can run consuming iterator on queue,
// and it will return items in decreasing order
for (key, priority) in queue_clone{
println!("Priority of key {} is {}", key, priority);
}
// Popping always will return the biggest element
assert_eq!(queue.pop(), Some(("First", 5)));
// We can change priority of item by key:
queue.set_priority(&"Fourth", 10);
// And get it
assert_eq!(queue.get_priority(&"Fourth"), Some(&10));
// Now biggest element is Fourth
assert_eq!(queue.pop(), Some(("Fourth", 10)));
// We can also decrease priority!
queue.set_priority(&"Second", -1);
assert_eq!(queue.pop(), Some(("Third", 3)));
assert_eq!(queue.pop(), Some(("Fifth", 1)));
assert_eq!(queue.pop(), Some(("Second", -1)));
// Now queue is empty
assert_eq!(queue.pop(), None);
// We can clear queue
queue.clear();
assert!(queue.is_empty());
§Partial ord queue
If you need to use float values (which don’t implement Ord) as priority, you can use some wrapper that implement it:
use keyed_priority_queue::KeyedPriorityQueue;
use std::cmp::{Ord, Ordering, Eq, PartialEq, PartialOrd};
#[derive(Debug)]
struct OrdFloat(f32);
impl PartialOrd for OrdFloat {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(&other)) }
}
impl Eq for OrdFloat {}
impl PartialEq for OrdFloat {
fn eq(&self, other: &Self) -> bool { self.cmp(&other) == Ordering::Equal }
}
impl Ord for OrdFloat {
fn cmp(&self, other: &Self) -> Ordering {
self.0.partial_cmp(&other.0)
.unwrap_or(if self.0.is_nan() && other.0.is_nan() {
Ordering::Equal
} else if self.0.is_nan() {
Ordering::Less
} else { Ordering::Greater })
}
}
let mut queue = KeyedPriorityQueue::new();
queue.push(5, OrdFloat(5.0));
queue.push(4, OrdFloat(4.0));
assert_eq!(queue.pop(), Some((5, OrdFloat(5.0))));
assert_eq!(queue.pop(), Some((4, OrdFloat(4.0))));
assert_eq!(queue.pop(), None);
Implementations§
Source§impl<TKey: Hash + Eq, TPriority: Ord> KeyedPriorityQueue<TKey, TPriority, RandomState>
impl<TKey: Hash + Eq, TPriority: Ord> KeyedPriorityQueue<TKey, TPriority, RandomState>
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates an empty queue
§Examples
use keyed_priority_queue::KeyedPriorityQueue;
let mut queue = KeyedPriorityQueue::new();
queue.push("Key", 4);
Sourcepub fn with_capacity(capacity: usize) -> Self
pub fn with_capacity(capacity: usize) -> Self
Creates an empty queue with allocated memory enough
to keep capacity
elements without reallocation.
§Examples
use keyed_priority_queue::KeyedPriorityQueue;
let mut queue = KeyedPriorityQueue::with_capacity(10);
queue.push("Key", 4);
Source§impl<TKey: Hash + Eq, TPriority: Ord, S: BuildHasher> KeyedPriorityQueue<TKey, TPriority, S>
impl<TKey: Hash + Eq, TPriority: Ord, S: BuildHasher> KeyedPriorityQueue<TKey, TPriority, S>
Sourcepub fn with_hasher(hasher: S) -> Self
pub fn with_hasher(hasher: S) -> Self
Creates an empty queue with specific Hasher
§Examples
use keyed_priority_queue::KeyedPriorityQueue;
use std::collections::hash_map::RandomState;
let mut queue = KeyedPriorityQueue::with_hasher(RandomState::default());
queue.push("Key", 4);
Sourcepub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self
pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self
Creates an empty queue with allocated memory enough
to keep capacity
elements without reallocation.
Also useful when Hasher cannot be defaulted.
§Examples
use keyed_priority_queue::KeyedPriorityQueue;
use std::collections::hash_map::RandomState;
let mut queue = KeyedPriorityQueue::with_capacity_and_hasher(10, RandomState::default());
queue.push("Key", 4);
Sourcepub fn push(&mut self, key: TKey, priority: TPriority) -> Option<TPriority>
pub fn push(&mut self, key: TKey, priority: TPriority) -> Option<TPriority>
Adds new element to queue if missing key or replace its priority if key exists. In second case doesn’t replace key.
§Examples
use keyed_priority_queue::KeyedPriorityQueue;
let mut queue = KeyedPriorityQueue::new();
queue.push("First", 5);
assert_eq!(queue.peek(), Some((&"First", &5)));
queue.push("First", 10);
assert_eq!(queue.peek(), Some((&"First", &10)));
§Time complexity
Average complexity is O(log n) If elements pushed in descending order, amortized complexity is O(1).
The worst case is when reallocation appears. In this case complexity of single call is O(n).
Sourcepub fn pop(&mut self) -> Option<(TKey, TPriority)>
pub fn pop(&mut self) -> Option<(TKey, TPriority)>
Remove and return item with the maximal priority.
§Examples
use keyed_priority_queue::KeyedPriorityQueue;
let mut queue: KeyedPriorityQueue<i32, i32> = (0..5).map(|x|(x,x)).collect();
assert_eq!(queue.pop(), Some((4,4)));
assert_eq!(queue.pop(), Some((3,3)));
assert_eq!(queue.pop(), Some((2,2)));
assert_eq!(queue.pop(), Some((1,1)));
assert_eq!(queue.pop(), Some((0,0)));
§Time complexity
Cost of pop is always O(log n)
Sourcepub fn peek(&self) -> Option<(&TKey, &TPriority)>
pub fn peek(&self) -> Option<(&TKey, &TPriority)>
Sourcepub fn entry(&mut self, key: TKey) -> Entry<'_, TKey, TPriority, S>
pub fn entry(&mut self, key: TKey) -> Entry<'_, TKey, TPriority, S>
Gets the given key’s corresponding entry in the map for in-place manipulation.
§Time complexity
Amortized O(1), uses only one hash lookup
Sourcepub fn get_priority<Q>(&self, key: &Q) -> Option<&TPriority>
pub fn get_priority<Q>(&self, key: &Q) -> Option<&TPriority>
Get reference to the priority by key.
§Examples
use keyed_priority_queue::KeyedPriorityQueue;
let mut queue: KeyedPriorityQueue<&str, i32> = [("first", 0), ("second", 1), ("third", 2)]
.iter().cloned().collect();
assert_eq!(queue.get_priority(&"second"), Some(&1));
§Time complexity
O(1) in average (limited by hash map key lookup).
Sourcepub fn set_priority<Q>(
&mut self,
key: &Q,
priority: TPriority,
) -> Result<TPriority, SetPriorityNotFoundError>
pub fn set_priority<Q>( &mut self, key: &Q, priority: TPriority, ) -> Result<TPriority, SetPriorityNotFoundError>
Set new priority for existing key and reorder the queue.
Returns old priority if succeeds or SetPriorityNotFoundError
.
§Examples
use keyed_priority_queue::{KeyedPriorityQueue, SetPriorityNotFoundError};
let mut queue: KeyedPriorityQueue<&str, i32> = [("first", 0), ("second", 1), ("third", 2)]
.iter().cloned().collect();
assert_eq!(queue.set_priority(&"second", 5), Ok(1));
assert_eq!(queue.get_priority(&"second"), Some(&5));
assert_eq!(queue.pop(), Some(("second", 5)));
assert_eq!(queue.set_priority(&"Missing", 5), Err(SetPriorityNotFoundError{}));
§Time complexity
In best case O(1), in average costs O(log n).
Sourcepub fn remove<Q>(&mut self, key: &Q) -> Option<TPriority>
pub fn remove<Q>(&mut self, key: &Q) -> Option<TPriority>
Allow removing item by key. Returns priority if succeeds.
§Examples
use keyed_priority_queue::KeyedPriorityQueue;
let mut queue: KeyedPriorityQueue<i32, i32> = (0..5).map(|x|(x,x)).collect();
assert_eq!(queue.remove(&2), Some(2));
assert_eq!(queue.pop(), Some((4,4)));
assert_eq!(queue.pop(), Some((3,3)));
// There is no 2
assert_eq!(queue.pop(), Some((1,1)));
assert_eq!(queue.pop(), Some((0,0)));
assert_eq!(queue.remove(&10), None);
§Time complexity
On average the function will require O(log n) operations.
Sourcepub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(TKey, TPriority)>
pub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(TKey, TPriority)>
Allow removing item by key. Returns key and priority if succeeds.
§Examples
use keyed_priority_queue::KeyedPriorityQueue;
let mut queue: KeyedPriorityQueue<i32, i32> = (0..5).map(|x|(x,x)).collect();
assert_eq!(queue.remove_entry(&2), Some((2, 2)));
assert_eq!(queue.pop(), Some((4,4)));
assert_eq!(queue.pop(), Some((3,3)));
// There is no 2
assert_eq!(queue.pop(), Some((1,1)));
assert_eq!(queue.pop(), Some((0,0)));
assert_eq!(queue.remove_entry(&10), None);
§Time complexity
On average the function will require O(log n) operations.
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if queue is empty.
let mut queue = keyed_priority_queue::KeyedPriorityQueue::new();
assert!(queue.is_empty());
queue.push(0,5);
assert!(!queue.is_empty());
§Time complexity
Always O(1)
Sourcepub fn clear(&mut self)
pub fn clear(&mut self)
Make the queue empty.
use keyed_priority_queue::KeyedPriorityQueue;
let mut queue: KeyedPriorityQueue<i32, i32> = (0..5).map(|x|(x,x)).collect();
assert!(!queue.is_empty());
queue.clear();
assert!(queue.is_empty());
§Time complexity
Always O(n)
Sourcepub fn iter(&self) -> KeyedPriorityQueueBorrowIter<'_, TKey, TPriority, S> ⓘ
pub fn iter(&self) -> KeyedPriorityQueueBorrowIter<'_, TKey, TPriority, S> ⓘ
Create readonly borrowing iterator over heap
use keyed_priority_queue::KeyedPriorityQueue;
use std::collections::HashMap;
let queue: KeyedPriorityQueue<i32, i32> = (0..5).map(|x|(x,x)).collect();
let mut entries = HashMap::new();
for (&key, &priority) in queue.iter(){
entries.insert(key, priority);
}
let second_map: HashMap<i32, i32> = (0..5).map(|x|(x,x)).collect();
assert_eq!(entries, second_map);
§Time complexity
Iterating over whole queue is O(n)
Trait Implementations§
Source§impl<TKey, TPriority, S> Clone for KeyedPriorityQueue<TKey, TPriority, S>
impl<TKey, TPriority, S> Clone for KeyedPriorityQueue<TKey, TPriority, S>
Source§fn clone(&self) -> KeyedPriorityQueue<TKey, TPriority, S>
fn clone(&self) -> KeyedPriorityQueue<TKey, TPriority, S>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moreSource§impl<TKey: Hash + Eq + Debug, TPriority: Ord + Debug, S: BuildHasher> Debug for KeyedPriorityQueue<TKey, TPriority, S>
impl<TKey: Hash + Eq + Debug, TPriority: Ord + Debug, S: BuildHasher> Debug for KeyedPriorityQueue<TKey, TPriority, S>
Source§impl<TKey: Hash + Eq, TPriority: Ord, S: BuildHasher + Default> Default for KeyedPriorityQueue<TKey, TPriority, S>
impl<TKey: Hash + Eq, TPriority: Ord, S: BuildHasher + Default> Default for KeyedPriorityQueue<TKey, TPriority, S>
Source§impl<TKey: Hash + Eq, TPriority: Ord, S: BuildHasher + Default> FromIterator<(TKey, TPriority)> for KeyedPriorityQueue<TKey, TPriority, S>
impl<TKey: Hash + Eq, TPriority: Ord, S: BuildHasher + Default> FromIterator<(TKey, TPriority)> for KeyedPriorityQueue<TKey, TPriority, S>
Source§fn from_iter<T: IntoIterator<Item = (TKey, TPriority)>>(iter: T) -> Self
fn from_iter<T: IntoIterator<Item = (TKey, TPriority)>>(iter: T) -> Self
Allows building queue from iterator using collect()
.
At result it will be valid queue with unique keys.
§Examples
use keyed_priority_queue::KeyedPriorityQueue;
let mut queue: KeyedPriorityQueue<&str, i32> =
[("first", 0), ("second", 1), ("third", 2), ("first", -1)]
.iter().cloned().collect();
assert_eq!(queue.pop(), Some(("third", 2)));
assert_eq!(queue.pop(), Some(("second", 1)));
assert_eq!(queue.pop(), Some(("first", -1)));
assert_eq!(queue.pop(), None);
§Time complexity
O(n log n) in average.
Source§impl<TKey: Hash + Eq, TPriority: Ord> IntoIterator for KeyedPriorityQueue<TKey, TPriority>
impl<TKey: Hash + Eq, TPriority: Ord> IntoIterator for KeyedPriorityQueue<TKey, TPriority>
Source§fn into_iter(self) -> Self::IntoIter
fn into_iter(self) -> Self::IntoIter
Make iterator that return items in descending order.
§Examples
use keyed_priority_queue::KeyedPriorityQueue;
let mut queue: KeyedPriorityQueue<&str, i32> =
[("first", 0), ("second", 1), ("third", 2)]
.iter().cloned().collect();
let mut iterator = queue.into_iter();
assert_eq!(iterator.next(), Some(("third", 2)));
assert_eq!(iterator.next(), Some(("second", 1)));
assert_eq!(iterator.next(), Some(("first", 0)));
assert_eq!(iterator.next(), None);
§Time complexity
O(n log n) for iteration.