graph_collections/priority_queue.rs
1use crate::MinHeap;
2
3/// A keyed priority queue that pops by **lowest priority first**.
4///
5/// Backed by [`MinHeap`] with `(P, T)` pairs. Because Rust's tuple ordering
6/// is lexicographic, storing `(priority, value)` gives us priority ordering
7/// for free.
8///
9/// # Use case
10///
11/// This is the queue Dijkstra's algorithm uses:
12/// push a `(node, cost)` pair and always pop the cheapest node next.
13///
14/// # Examples
15///
16/// ```
17/// use graph_collections::PriorityQueue;
18///
19/// let mut pq: PriorityQueue<&str, u32> = PriorityQueue::new();
20///
21/// pq.push("low", 10);
22/// pq.push("high", 1);
23/// pq.push("medium", 5);
24///
25/// assert_eq!(pq.peek_priority(), Some(&1));
26///
27/// assert_eq!(pq.pop(), Some(("high", 1)));
28/// assert_eq!(pq.pop(), Some(("medium", 5)));
29/// assert_eq!(pq.pop(), Some(("low", 10)));
30/// assert!(pq.is_empty());
31/// ```
32#[derive(Debug, Clone)]
33pub struct PriorityQueue<T: Ord, P: Ord> {
34 /// Internally stores `(priority, value)` so [`MinHeap`]'s lexicographic
35 /// ordering promotes the smallest priority to the top.
36 heap: MinHeap<(P, T)>,
37}
38
39impl<T: Ord, P: Ord> Default for PriorityQueue<T, P> {
40 fn default() -> Self {
41 Self {
42 heap: MinHeap::new(),
43 }
44 }
45}
46
47impl<T: Ord, P: Ord> PriorityQueue<T, P> {
48 /// Creates a new, empty priority queue.
49 ///
50 /// # Examples
51 ///
52 /// ```
53 /// use graph_collections::PriorityQueue;
54 ///
55 /// let pq: PriorityQueue<&str, u32> = PriorityQueue::new();
56 /// assert!(pq.is_empty());
57 /// ```
58 pub fn new() -> Self {
59 Self::default()
60 }
61
62 /// Creates a new, empty priority queue with at least the given capacity
63 /// pre-allocated.
64 ///
65 /// # Examples
66 ///
67 /// ```
68 /// use graph_collections::PriorityQueue;
69 ///
70 /// let pq: PriorityQueue<u32, u32> = PriorityQueue::with_capacity(128);
71 /// assert!(pq.is_empty());
72 /// ```
73 pub fn with_capacity(capacity: usize) -> Self {
74 Self {
75 heap: MinHeap::with_capacity(capacity),
76 }
77 }
78}
79
80impl<T: Ord, P: Ord> PriorityQueue<T, P> {
81 /// Returns `true` if the queue contains no elements.
82 ///
83 /// # Examples
84 ///
85 /// ```
86 /// use graph_collections::PriorityQueue;
87 ///
88 /// let mut pq: PriorityQueue<u32, u32> = PriorityQueue::new();
89 /// assert!(pq.is_empty());
90 /// pq.push(1, 10);
91 /// assert!(!pq.is_empty());
92 /// ```
93 #[inline]
94 pub fn is_empty(&self) -> bool {
95 self.heap.is_empty()
96 }
97
98 /// Returns the number of elements in the queue.
99 ///
100 /// # Examples
101 ///
102 /// ```
103 /// use graph_collections::PriorityQueue;
104 ///
105 /// let mut pq: PriorityQueue<u32, u32> = PriorityQueue::new();
106 /// pq.push(1, 5);
107 /// pq.push(2, 3);
108 /// assert_eq!(pq.len(), 2);
109 /// ```
110 #[must_use]
111 #[inline]
112 pub fn len(&self) -> usize {
113 self.heap.len()
114 }
115}
116
117impl<T: Ord, P: Ord> PriorityQueue<T, P> {
118 /// Returns a reference to the **lowest priority** value without removing it,
119 /// or `None` if empty.
120 ///
121 /// # Examples
122 ///
123 /// ```
124 /// use graph_collections::PriorityQueue;
125 ///
126 /// let mut pq: PriorityQueue<&str, u32> = PriorityQueue::new();
127 /// assert_eq!(pq.peek_priority(), None);
128 /// pq.push("a", 3);
129 /// pq.push("b", 1);
130 /// assert_eq!(pq.peek_priority(), Some(&1));
131 /// assert_eq!(pq.len(), 2); // unchanged
132 /// ```
133 #[must_use]
134 #[inline]
135 pub fn peek_priority(&self) -> Option<&P> {
136 self.heap.peek().map(|(p, _)| p)
137 }
138
139 /// Returns a reference to the **value** with the lowest priority without
140 /// removing it, or `None` if empty.
141 ///
142 /// # Examples
143 ///
144 /// ```
145 /// use graph_collections::PriorityQueue;
146 ///
147 /// let mut pq: PriorityQueue<&str, u32> = PriorityQueue::new();
148 /// pq.push("high", 1);
149 /// pq.push("low", 9);
150 /// assert_eq!(pq.peek_value(), Some(&"high"));
151 /// ```
152 #[must_use]
153 #[inline]
154 pub fn peek_value(&self) -> Option<&T> {
155 self.heap.peek().map(|(_, v)| v)
156 }
157}
158
159impl<T: Ord, P: Ord> PriorityQueue<T, P> {
160 /// Inserts `value` with the given `priority` in **O(log n)**.
161 ///
162 /// Duplicate priorities are allowed; ties are broken by the natural order
163 /// of `T` (because tuples are compared lexicographically).
164 ///
165 /// # Examples
166 ///
167 /// ```
168 /// use graph_collections::PriorityQueue;
169 ///
170 /// let mut pq: PriorityQueue<&str, u32> = PriorityQueue::new();
171 /// pq.push("task-a", 2);
172 /// pq.push("task-b", 1);
173 /// assert_eq!(pq.peek_priority(), Some(&1));
174 /// ```
175 #[inline]
176 pub fn push(&mut self, value: T, priority: P) {
177 self.heap.push((priority, value));
178 }
179
180 /// Removes and returns `(value, priority)` for the element with the
181 /// **lowest priority**, or `None` if empty.
182 ///
183 /// # Examples
184 ///
185 /// ```
186 /// use graph_collections::PriorityQueue;
187 ///
188 /// let mut pq: PriorityQueue<&str, u32> = PriorityQueue::new();
189 /// assert_eq!(pq.pop(), None);
190 /// pq.push("a", 3);
191 /// pq.push("b", 1);
192 /// pq.push("c", 2);
193 /// assert_eq!(pq.pop(), Some(("b", 1)));
194 /// assert_eq!(pq.pop(), Some(("c", 2)));
195 /// assert_eq!(pq.pop(), Some(("a", 3)));
196 /// ```
197 #[inline]
198 pub fn pop(&mut self) -> Option<(T, P)> {
199 self.heap.pop().map(|(p, v)| (v, p))
200 }
201
202 /// Removes all elements from the queue.
203 ///
204 /// # Examples
205 ///
206 /// ```
207 /// use graph_collections::PriorityQueue;
208 ///
209 /// let mut pq: PriorityQueue<u32, u32> = PriorityQueue::new();
210 /// pq.push(1, 10);
211 /// pq.push(2, 5);
212 /// pq.clear();
213 /// assert!(pq.is_empty());
214 /// ```
215 #[inline]
216 pub fn clear(&mut self) {
217 self.heap.clear();
218 }
219}
220
221impl<T: Ord, P: Ord> FromIterator<(T, P)> for PriorityQueue<T, P> {
222 /// Builds a `PriorityQueue` from an iterator of `(value, priority)` pairs.
223 ///
224 /// # Examples
225 ///
226 /// ```
227 /// use graph_collections::PriorityQueue;
228 ///
229 /// let pq: PriorityQueue<&str, u32> = vec![
230 /// ("slow", 10u32),
231 /// ("fast", 1),
232 /// ("medium", 5),
233 /// ]
234 /// .into_iter()
235 /// .collect();
236 ///
237 /// assert_eq!(pq.peek_priority(), Some(&1));
238 /// assert_eq!(pq.len(), 3);
239 /// ```
240 fn from_iter<I: IntoIterator<Item = (T, P)>>(iter: I) -> Self {
241 // Swap to (P, T) for MinHeap's ordering, then wrap.
242 let heap: MinHeap<(P, T)> = iter.into_iter().map(|(v, p)| (p, v)).collect();
243 Self { heap }
244 }
245}
246
247impl<T: Ord, P: Ord> Extend<(T, P)> for PriorityQueue<T, P> {
248 /// Pushes all `(value, priority)` pairs from the iterator into the queue.
249 ///
250 /// # Examples
251 ///
252 /// ```
253 /// use graph_collections::PriorityQueue;
254 ///
255 /// let mut pq: PriorityQueue<&str, u32> = PriorityQueue::new();
256 /// pq.push("seed", 5);
257 /// pq.extend([("a", 2u32), ("b", 8), ("c", 1)]);
258 /// assert_eq!(pq.peek_priority(), Some(&1));
259 /// assert_eq!(pq.len(), 4);
260 /// ```
261 fn extend<I: IntoIterator<Item = (T, P)>>(&mut self, iter: I) {
262 for (v, p) in iter {
263 self.push(v, p);
264 }
265 }
266}