collections_more/queue/priority_queue/mod.rs
1// MIT License Mayeul (Mike) Fournial <mayeul.fournial@outlook.com> - 2017
2
3use std::fmt::Debug;
4
5/// A priority queue implementation based on an unbounded max heap.
6/// The elements are ordered by implementation of the PartialOrd trait with
7/// the biggest element readable in `O(1)` time
8///
9/// # Examples
10///
11/// ```
12/// extern crate collections_more;
13/// use collections_more::queue::priority_queue::PriorityQueue;
14/// // snip ..
15/// # fn main() {
16/// let mut pq: PriorityQueue<i32> = PriorityQueue::new();
17/// pq.push(4);
18/// pq.push(-55);
19/// pq.push(9);
20/// pq.push(0);
21///
22/// assert_eq!(4, pq.len()); // Length of the priority queue
23/// assert_eq!(Some(9), pq.poll()); // Removes the biggest element
24/// assert_eq!(3, pq.len()); // Length after polling the biggest element
25///
26/// // Polls max element of the priority queue on each iteration
27/// // Equivalent to "Heapsort" but space inefficient
28/// let mut sorted = Vec::with_capacity(pq.len());
29/// for elem in pq {
30/// sorted.push(elem)
31/// }
32/// assert_eq!(vec!(4, 0, -55), sorted);
33/// # }
34///
35/// ```
36///
37/// # Macro and creation
38///
39/// For fast creation of priority_queues, one can use the macro that behaves
40/// like the `vec` macro (e.g. `let mut pq = pqueue!(3, 2, 7, -3)`,
41/// `let pq = pqueue!['c', 'h', 'a', 'r']`).
42/// We do not provide a `unsafe fn from_raw_part(ptr: *mut T, length: usize,
43/// capacity: usize) -> PriorityQueue<T>) builder as it is too unsafe to do so.
44///
45///
46/// # Slicing
47///
48/// It is possible to retrieve the priority queue as a slice. However it'll be
49/// in a heap order, not consecutive natural ordering of the elements.
50///
51#[derive(Debug, PartialEq)]
52pub struct PriorityQueue<T: PartialOrd + PartialEq + Debug> {
53 heap: Vec<T>,
54 next_index: usize
55}
56
57impl<T: PartialOrd + PartialEq + Debug> PriorityQueue<T> {
58 /// Constructs a new, empty `PriorityQueue<T>`.
59 ///
60 /// # Examples
61 ///
62 /// ```
63 /// # extern crate collections_more;
64 /// # use collections_more::queue::priority_queue::PriorityQueue;
65 /// # fn main() {
66 /// # #[allow(unused_mut)]
67 /// let mut pq: PriorityQueue<i32> = PriorityQueue::new();
68 /// # }
69 /// ```
70 #[inline]
71 pub fn new() -> PriorityQueue<T> {
72 PriorityQueue {
73 heap: Vec::new(),
74 next_index: 0,
75 }
76 }
77
78 /// Constructs a new, empty `PriorityQueue<T>` with the specified capacity.
79 ///
80 /// The priority queue will be able to hold exactly `capacity`
81 /// elements without reallocating.
82 ///
83 /// # Examples
84 ///
85 /// ```
86 /// # extern crate collections_more;
87 /// # use collections_more::queue::priority_queue::PriorityQueue;
88 /// # fn main() {
89 /// let mut pq = PriorityQueue::with_capacity(10);
90 ///
91 /// // The pqueue is empty, even though it has capacity of 10
92 /// assert_eq!(pq.len(), 0);
93 ///
94 /// // These are all done without reallocating...
95 /// for i in 0..10 {
96 /// pq.push(i);
97 /// }
98 ///
99 /// // ...but this may make the pqueue to reallocate
100 /// pq.push(11);
101 /// # }
102 /// ```
103 #[inline]
104 pub fn with_capacity(capacity: usize) -> PriorityQueue<T> {
105 PriorityQueue {
106 heap: Vec::with_capacity(capacity),
107 next_index: 0,
108 }
109 }
110
111 /// Add an element to the priority queue while keeping the most desired
112 /// element accessible in the same time
113 ///
114 /// # Example
115 ///
116 /// ```
117 /// # extern crate collections_more;
118 /// # use collections_more::queue::priority_queue::PriorityQueue;
119 /// # fn main() {
120 /// let mut pq = PriorityQueue::with_capacity(2);
121 /// pq.push(2);
122 /// pq.push(6);
123 /// assert_eq!(2, pq.len()); // length of the pqueue
124 /// assert_eq!(Some(6), pq.poll()); // max element of pqueue
125 /// # }
126 /// ```
127 pub fn push(&mut self, elem: T) {
128 let mut current = self.next_index;
129 self.heap.push(elem);
130 self.next_index += 1;
131
132 while current != 0 && self.heap[current] > self.heap[parent(current)] {
133 self.swap(current, parent(current));
134 current = parent(current);
135 }
136 }
137
138 /// Returns the number of elements in the queue
139 ///
140 /// # Example
141 ///
142 /// ```
143 /// # extern crate collections_more;
144 /// # use collections_more::queue::priority_queue::PriorityQueue;
145 /// # fn main() {
146 /// let mut pq = PriorityQueue::with_capacity(2);
147 /// assert_eq!(0, pq.len()); // no elements
148 /// pq.push(2);
149 /// assert_eq!(1, pq.len()); // one elements
150 /// pq.push(6);
151 /// assert_eq!(2, pq.len());
152 /// pq.poll();
153 /// assert_eq!(1, pq.len()); // one elements again
154 /// # }
155 /// ```
156 #[inline]
157 pub fn len(&self) -> usize {
158 self.heap.len() // or could equally be self.next_index
159 }
160
161 /// Returns true if there is no element in the queue.
162 /// Equivalent to `pq.len() == 0`
163 ///
164 /// # Example
165 ///
166 /// ```
167 /// # extern crate collections_more;
168 /// # use collections_more::queue::priority_queue::PriorityQueue;
169 /// # fn main() {
170 /// let mut pq = PriorityQueue::with_capacity(2);
171 /// assert!(pq.is_empty()); // no elements
172 /// pq.push(2);
173 /// assert!(!pq.is_empty()); // one elements
174 /// pq.poll();
175 /// assert!(pq.is_empty()); // no element again
176 /// # }
177 /// ```
178 #[inline]
179 pub fn is_empty(&self) -> bool {
180 self.heap.is_empty()
181 }
182
183 /// Returns a borrow to the biggest element of the queue (O(1) time).
184 /// **returns `None` if queue is empty**
185 ///
186 /// # Example
187 ///
188 /// ```
189 /// # extern crate collections_more;
190 /// # use collections_more::queue::priority_queue::PriorityQueue;
191 /// # fn main() {
192 /// let mut pq = PriorityQueue::with_capacity(2);
193 /// pq.push(2);
194 /// pq.push(6);
195 /// assert_eq!(Some(&6), pq.peek());
196 /// # }
197 /// ```
198 pub fn peek(&self) -> Option<&T> {
199 if self.heap.is_empty() {
200 return None;
201 }
202 Some(&self.heap[0])
203 }
204
205 /// Retrieves the biggest element of the queue, therefore deleting it from
206 /// the queue.
207 /// **returns `None` if queue is empty**
208 ///
209 /// # Example
210 ///
211 /// ```
212 /// # extern crate collections_more;
213 /// # use collections_more::queue::priority_queue::PriorityQueue;
214 /// # fn main() {
215 /// let mut pq = PriorityQueue::with_capacity(2);
216 /// pq.push(2);
217 /// pq.push(6);
218 /// assert_eq!(Some(6), pq.poll());
219 /// assert_eq!(1, pq.len());
220 /// # }
221 /// ```
222 pub fn poll(&mut self) -> Option<T> {
223 if self.is_empty() {
224 return None;
225 }
226
227 self.next_index -= 1;
228 self.heap.swap(0, self.next_index);
229 if self.next_index != 0 {
230 self.siftdown(0);
231 }
232
233 self.heap.pop()
234 }
235
236 /// Extracts a slice containing the entire priority queue.
237 /// *Note the order of the slice will be a heap order, not sorted*
238 pub fn as_slice(&self) -> &[T] {
239 self.heap.as_slice()
240 }
241
242 #[inline]
243 fn swap(&mut self, a: usize, b: usize) {
244 self.heap.swap(a, b)
245 }
246
247 fn siftdown(&mut self, start_index: usize) {
248 let mut index = start_index;
249
250 while !self.is_leaf(index) {
251 let left_ch = left_ch(index);
252 let right_ch = right_ch(index);
253
254 let max_ch_index = if right_ch < self.next_index && self.heap[left_ch] < self.heap[right_ch] {
255 right_ch
256 } else {
257 left_ch
258 };
259
260 if self.heap[max_ch_index] < self.heap[index] {
261 return
262 }
263
264 self.swap(max_ch_index, index);
265 index = max_ch_index;
266 }
267 }
268
269 fn is_leaf(&self, index: usize) -> bool {
270 index >= self.next_index / 2 && index < self.next_index
271 }
272}
273
274fn parent(child: usize) -> usize {
275 (child - 1) / 2
276}
277
278fn right_ch(parent: usize) -> usize {
279 parent * 2 + 2
280}
281
282fn left_ch(parent: usize) -> usize {
283 parent * 2 + 1
284}
285
286impl<T: PartialOrd + Debug> Iterator for PriorityQueue<T> {
287 type Item = T;
288
289 fn next(&mut self) -> Option<T> {
290 self.poll()
291 }
292}
293
294#[macro_export]
295macro_rules! pqueue {
296 () => (PriorityQueue::new());
297 ($elem:expr; $n:expr) => (
298 {
299 let mut temp_pq = PriorityQueue::new();
300 temp_pq.heap = vec![$elem; $n];
301 temp_pq.next_index = $n - 1;
302 }
303 );
304 ($($x:expr),*) => (
305 {
306 let mut temp_pq = PriorityQueue::new();
307 $(
308 temp_pq.push($x);
309 )*
310 temp_pq
311 }
312 );
313 ( $($x: expr,)* ) => (pqueue![$($x),*])
314}
315
316
317#[cfg(test)]
318mod tests {
319 use super::*;
320
321 #[test]
322 fn priority_queue_creates_with_new_factory() {
323 let _: PriorityQueue<i32> = PriorityQueue::new();
324 }
325
326 #[test]
327 fn priority_queue_can_create_with_empty_macro() {
328 let _: PriorityQueue<i32> = pqueue!();
329 }
330
331 #[test]
332 fn priority_queue_returns_none_if_empty() {
333 let mut pq: PriorityQueue<i32> = PriorityQueue::new();
334 assert_eq!(None, pq.poll());
335 pq.push(4);
336 pq.poll();
337 assert_eq!(None, pq.poll());
338 }
339
340 #[test]
341 fn priority_queue_is_empty_with_new_factory() {
342 let pq: PriorityQueue<i32> = PriorityQueue::new();
343 assert!(pq.is_empty());
344 }
345
346 #[test]
347 fn priority_queue_is_empty_with_macro() {
348 let pq: PriorityQueue<i32> = pqueue!();
349 assert!(pq.is_empty());
350 }
351
352 #[test]
353 fn priority_queue_can_insert_with_factory() {
354 let mut pq = PriorityQueue::new();
355 pq.push(1);
356 pq.push(5);
357 assert_eq!(2, pq.len());
358 }
359
360 #[test]
361 fn priority_queue_can_insert_with_macro() {
362 let pq = pqueue!(1, 2, 3);
363 assert_eq!(3, pq.len());
364 }
365
366 #[test]
367 fn priority_queue_can_insert_duplicates() {
368 let pq = pqueue!(1, 1, 1, 1);
369 assert_eq!(4, pq.len());
370 }
371
372 #[test]
373 fn priority_queue_can_be_equated() {
374 let pq1 = pqueue!('c', 'd', 'p');
375 let pq2 = pqueue!('c', 'p', 'd');
376 assert_eq!(pq1, pq2);
377 }
378
379 #[test]
380 fn priority_queue_can_retrieve_largest() {
381 let mut pq = PriorityQueue::new();
382 pq.push(-4);
383 pq.push(5);
384 pq.push(-3);
385 pq.push(8);
386 pq.push(0);
387 assert_eq!(&8, pq.peek().unwrap());
388 }
389
390 #[test]
391 fn priority_queue_can_peek_with_macro() {
392 let pq1 = pqueue!(1);
393 assert_eq!(&1, pq1.peek().unwrap());
394 let pq2 = pqueue!(-5, 4, 3, 2, 1);
395 assert_eq!(&4, pq2.peek().unwrap());
396 let pq3 = pqueue!('1', '2', '3', '4', '5', '6', '7', '8');
397 assert_eq!(&'8', pq3.peek().unwrap());
398 }
399
400 #[test]
401 fn priority_queue_reorders_on_retrival_of_maximum() {
402 let mut pq = pqueue![1, -2, 32, -4, 5, 6, -90];
403 pq.poll();
404 pq.poll();
405 pq.poll();
406 pq.poll();
407 assert_eq!(vec!(-2, -4, -90).as_slice(), pq.as_slice());
408 }
409
410 #[test]
411 fn priority_queue_can_be_iterated_in_order() {
412 let pq = pqueue!(1, 6, 2, 8, 4, 3, 2, 10, 7);
413 let mut actual = vec!();
414 for elem in pq {
415 actual.push(elem);
416 }
417 let expected = vec!(10, 8, 7, 6, 4, 3, 2, 2, 1);
418 assert_eq!(expected, actual);
419 }
420
421 #[test]
422 fn priority_queue_can_be_turned_into_a_slice() {
423 let pq = pqueue!(1, 6, 2, 8, 4, 3, 2, 10, 7);
424 let expected = vec!(10, 8, 3, 7, 4, 2, 2, 1, 6);
425 assert_eq!(expected.as_slice(), pq.as_slice());
426 }
427
428 #[test]
429 fn priority_queue_works_with_heap_elements() {
430 let pq = pqueue!(Box::new(3), Box::new(-2), Box::new(-9), Box::new(-2),
431 Box::new(2), Box::new(3), Box::new(99), Box::new(14), Box::new(5));
432 let expected = vec!(Box::new(99), Box::new(14), Box::new(5), Box::new(3),
433 Box::new(3), Box::new(2), Box::new(-2), Box::new(-2), Box::new(-9));
434 let mut actual = Vec::with_capacity(9);
435 for elem in pq {
436 actual.push(elem);
437 }
438 assert_eq!(expected, actual);
439 }
440}