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}