prio_queue/
lib.rs

1////////////////////////////////////////////////////////////////////////////////
2//! A simple priority queue implemented as a binary heap stored in a `Vec<T>`.
3//!
4//! This implementation aims to be simple and more flexible than the one
5//! provided by the standard library. It relies on a given function to determine
6//! priority between elements. Let you acces the underlying `Vec<T>` with
7//! consistency check or not.
8
9use std::fmt;
10
11/// A priority queue implemented as a binary heap stored in a `Vec<T>`
12///
13/// This implementation aims to be simple and more flexible than the one
14/// provided by the standard library. It rely on a given function to determine
15/// priority between elements. Let you acces the underlying `Vec<T>` with
16/// consistency check or not.
17/// ```
18/// # use prio_queue::PrioQueue;
19/// let mut queue = PrioQueue::new(|l, r| l < r);
20/// queue.push(42);
21/// queue.push(32);
22/// queue.push(64);
23/// assert_eq!(queue.pop(), Some(32));
24/// assert_eq!(queue.pop(), Some(42));
25/// assert_eq!(queue.pop(), Some(64));
26/// assert_eq!(queue.pop(), None);
27/// ```
28///
29/// ## Complexity
30///
31/// Pushing an element has a maximum complexity of *O*(log(n)).
32///
33/// Poping en element has a maximum complexity of *O*(log(n)).
34#[derive(Clone)]
35pub struct PrioQueue<T> {
36    prio: fn(&T, &T)->bool,
37    tree: Vec<T>,
38}
39impl<T> PrioQueue<T> {
40
41    /// Constructs a new, empty `PrioQueue<T>`.
42    pub fn new(prio: fn(&T, &T)->bool) -> Self {
43        Self {
44            prio,
45            tree: Vec::new(),
46        }
47    }
48
49    pub fn with_capacity(capacity: usize, prio: fn(&T, &T)->bool) -> Self {
50        Self {
51            prio,
52            tree: Vec::with_capacity(capacity),
53        }
54    }
55
56    /// Convenient function that uses `|l, r| l < r` as the priority function.
57    pub fn new_min() -> Self
58    where T: PartialOrd
59    {
60        Self::new(|l, r| l < r)
61    }
62
63    /// Convenient function that uses `|l, r| l > r` as the priority function.
64    pub fn new_max() -> Self
65    where T: PartialOrd
66    {
67        Self::new(|l, r| l > r)
68    }
69
70    /// Inserts an element in the queue.
71    pub fn push(&mut self, value: T) {
72        let index = self.len();
73        self.tree.push(value);
74        self.bubble_up(index);
75    }
76
77    /// Removes the top element of the queue.
78    pub fn pop(&mut self) -> Option<T> {
79        if self.len() == 0 {
80            None
81        }
82        else {
83            let poped = self.tree.swap_remove(0);
84            if self.len() > 0 {
85                self.bubble_down(0);
86            }
87            Some(poped)
88        }
89    }
90
91    /// Removes a given element.
92    pub fn remove(&mut self, index: usize) -> T {
93        assert!(index < self.len());
94        let poped = self.tree.swap_remove(index);
95        if index < self.len() {
96            self.bubble_up(index);
97            self.bubble_down(index);
98        }
99        poped
100    }
101
102    /// Returns a draining iterator yielding element in priority order.
103    pub fn drain(&mut self) -> Drain<T> {
104        Drain {
105            inner: self
106        }
107    }
108
109    /// Retains only the elements specified by the predicate.
110    pub fn retain(&mut self, mut pred: impl FnMut(&T)->bool) {
111        let mut index = 0;
112        while index < self.len() {
113            if pred(&self[index]) {
114                self.bubble_up(index);
115                index += 1;
116            }
117            else {
118                self.tree.swap_remove(index);
119            }
120        }
121    }
122
123    fn bubble_up(&mut self, mut index: usize) {
124        debug_assert!(index < self.len());
125        while let Some(parent) = self.parent(index) {
126            if self.is_prio(index, parent) {
127                self.tree.swap(index, parent);
128                index = parent;
129            }
130            else {
131                break
132            }
133        }
134    }
135
136    fn bubble_down(&mut self, mut index: usize) {
137        debug_assert!(index < self.len());
138        while let Some((left, right)) = self.childs(index) {
139            let result = if let Some(right) = right {
140                if self.is_prio(left, right) {
141                    if self.is_prio(left, index) {
142                        Some(left)
143                    }
144                    else if self.is_prio(right, index) {
145                        Some(right)
146                    }
147                    else {
148                        None
149                    }
150                }
151                else {
152                    if self.is_prio(right, index) {
153                        Some(right)
154                    }
155                    else if self.is_prio(left, index) {
156                        Some(left)
157                    }
158                    else {
159                        None
160                    }
161                }
162            }
163            else {
164                if self.is_prio(left, index) {
165                    Some(left)
166                }
167                else {
168                    None
169                }
170            };
171            if let Some(result) = result {
172                self.tree.swap(result, index);
173                index = result;
174            }
175            else {
176                break;
177            }
178        }
179    }
180
181    /// Tests whether `lhs` has priority over `rhs`.
182    pub fn is_prio(&self, lhs: usize, rhs: usize) -> bool {
183        assert!(lhs < self.len());
184        assert!(rhs < self.len());
185        assert!(lhs != rhs);
186        (self.prio)(&self[lhs], &self[rhs])
187    }
188
189    /// Returns the parent of the given element in the heap.
190    pub fn parent(&self, index: usize) -> Option<usize> {
191        assert!(index < self.len());
192        match index {
193            0 => None,
194            n => Some((n + 1) / 2 - 1),
195        }
196    }
197
198    /// Returns the childs of the given element in the heap.
199    pub fn childs(&self, index: usize) -> Option<(usize, Option<usize>)> {
200        let right = (index + 1) * 2;
201        let left = right - 1;
202        match (left < self.len(), right < self.len()) {
203            ( true,  true) => Some((left, Some(right))),
204            ( true, false) => Some((left, None)),
205            (false,     _) => None,
206        }
207    }
208
209    /// Let you access modify the underlying `Vec<T>` without checking consistency.
210    pub fn unchecked_mut(&mut self) -> &mut Vec<T> {
211        &mut self.tree
212    }
213
214    /// Let you access modify the underlying `Vec<T>` and will check consistency.
215    pub fn checked_mut(&mut self) -> CheckedMut<T> {
216        CheckedMut{ inner: self }
217    }
218
219    /// Tests whether the heap is in a consistent state.
220    pub fn check_consistency(&self) -> bool {
221        (1..self.len()).all(|i| self.is_prio(self.parent(i).unwrap(), i))
222    }
223
224    /// Repair heap consistency if broken.
225    pub fn restore_consistency(&mut self) {
226        for i in 1..self.len() {
227            self.bubble_up(i);
228        }
229    }
230
231    ////////////////////////////////////////////////////////////////////////////////
232    /// Builds a heap using the given `vec`.
233    pub fn from_vec(vec: Vec<T>, prio: fn(&T, &T)->bool) -> Self {
234        let mut queue = Self {
235            prio,
236            tree: vec,
237        };
238        queue.restore_consistency();
239        queue
240    }
241
242    /// Use the given `vec` as the heap and checking its consistency.
243    pub fn from_vec_checked(vec: Vec<T>, prio: fn(&T, &T)->bool) -> Self {
244        let queue = Self {
245            prio,
246            tree: vec,
247        };
248        assert!(queue.check_consistency());
249        queue
250    }
251
252    /// Use the given `vec` as the heap without checking its consistency.
253    pub fn from_vec_unchecked(vec: Vec<T>, prio: fn(&T, &T)->bool) -> Self {
254        Self {
255            prio,
256            tree: vec,
257        }
258    }
259
260    /// Buils the queue from an iterator.
261    pub fn from_iter<I: IntoIterator<Item=T>>(iter: I, prio: fn(&T, &T)->bool) -> Self {
262        Self::from_vec(iter.into_iter().collect(), prio)
263    }
264}
265
266pub struct CheckedMut<'a, T> {
267    inner: &'a mut PrioQueue<T>,
268}
269impl<'a, T> std::ops::Deref for CheckedMut<'a, T> {
270    type Target = Vec<T>;
271    fn deref(&self) -> &Self::Target {
272        &self.inner.tree
273    }
274}
275impl<'a, T> std::ops::DerefMut for CheckedMut<'a, T> {
276    fn deref_mut(&mut self) -> &mut Self::Target {
277        &mut self.inner.tree
278    }
279}
280impl<'a, T> Drop for CheckedMut<'a, T> {
281    fn drop(&mut self) {
282        assert!(self.inner.check_consistency());
283    }
284}
285
286impl<T: fmt::Debug> fmt::Debug for PrioQueue<T> {
287    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
288        self.tree.fmt(f)
289    }
290}
291impl<T: fmt::Display> fmt::Display for PrioQueue<T> {
292    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
293        let width = f.width().unwrap_or(3);
294        let len = (self.len() + 1).next_power_of_two();
295        let pow = len.trailing_zeros() as usize;
296        let wl = (width - 1) / 2;
297        let wr = (width - 1) - wl;
298        for i in 0..pow {
299            let span = (1 << (pow - 1 - i)) - 1;
300            for j in 0..(1 << i) {
301                let elem = (1 << i) - 1 + j;
302                let childs = self.childs(elem);
303                match childs {
304                    None => {
305                        write!(f, "{: >1$}", "", width * span)?;
306                        if elem < self.len() {
307                            write!(f, "{: ^1$}", self[elem], width)?;
308                        }
309                        else {
310                            write!(f, "{: >1$}", "", width)?;
311                        }
312                        write!(f, "{: >1$}", "", width * span)?;
313                    }
314                    Some((_, right)) => {
315                        write!(f, "{: >1$}", "", width * (span / 2) + wl)?;
316                        write!(f, "╭")?;
317                        write!(f, "{:─>1$}", "", width * (span / 2) + wr)?;
318                        write!(f, "{:─^1$}", self[elem], width)?;
319                        if let Some(_) = right {
320                            write!(f, "{:─>1$}", "", width * (span / 2) + wl)?;
321                            write!(f, "╮")?;
322                            write!(f, "{: >1$}", "", width * (span / 2) + wr)?;
323                        }
324                        else {
325                            write!(f, "{: >1$}", "", width * span)?;
326                        }
327                    }
328                }
329                write!(f, "{: >1$}", "", width)?;
330            }
331            writeln!(f, )?;
332        }
333        Ok(())
334    }
335}
336
337impl<T> std::ops::Deref for PrioQueue<T> {
338    type Target = [T];
339    fn deref(&self) -> &Self::Target {
340        &self.tree
341    }
342}
343
344pub struct Drain<'a, T> {
345    inner: &'a mut PrioQueue<T>,
346}
347impl<'a, T> Iterator for Drain<'a, T> {
348    type Item = T;
349    fn next(&mut self) -> Option<Self::Item> {
350        self.inner.pop()
351    }
352}
353
354pub struct IntoIter<T> {
355    inner: PrioQueue<T>,
356}
357impl<T> Iterator for IntoIter<T> {
358    type Item = T;
359    fn next(&mut self) -> Option<Self::Item> {
360        self.inner.pop()
361    }
362}
363
364impl<T> IntoIterator for PrioQueue<T> {
365    type Item = T;
366    type IntoIter = IntoIter<T>;
367    fn into_iter(self) -> Self::IntoIter {
368        IntoIter{
369            inner: self
370        }
371    }
372}
373
374impl<T> Extend<T> for PrioQueue<T> {
375    fn extend<I>(&mut self, iter: I)
376    where I: IntoIterator<Item = T>
377    {
378        for elem in iter {
379            self.push(elem);
380        }
381    }
382}
383
384impl<T: PartialOrd> std::iter::FromIterator<T> for PrioQueue<T> {
385    fn from_iter<I>(iter: I) -> Self
386    where I: IntoIterator<Item = T>
387    {
388        let mut queue = Self::new(|l, r| l < r);
389        queue.extend(iter);
390        queue
391    }
392}
393
394#[cfg(test)]
395mod tests {
396    use super::*;
397    #[test]
398    fn sorts() {
399        use rand::{Rng, SeedableRng, rngs::SmallRng};
400        let mut rng = SmallRng::seed_from_u64(9320154);
401        for _i in 0..100 {
402            let len = rng.gen_range(0..128);
403            // println!("round {}/10: len = {}", i + 1, len);
404            let mut values = Vec::with_capacity(len);
405            for _ in 0..len {
406                values.push(rng.gen_range(0..100));
407            }
408            let queue: PrioQueue<_> = values.iter().copied().collect();
409            // print!("{:2}", queue);
410            let result: Vec<_> = queue.into_iter().collect();
411            values.sort();
412            assert_eq!(values, result);
413        }
414    }
415    #[test]
416    fn remove() {
417        use rand::{Rng, SeedableRng, rngs::SmallRng};
418        let mut rng = SmallRng::seed_from_u64(885301);
419        for _i in 0..100 {
420            let len = rng.gen_range(0..128);
421            let remove = rng.gen_range(0..=len);
422            // println!("round {}/10: len = {}, remove = {}", i + 1, len, remove);
423            let mut values = Vec::with_capacity(len);
424            for _ in 0..len {
425                values.push(rng.gen_range(0..100));
426            }
427            let mut queue: PrioQueue<_> = values.iter().copied().collect();
428            // print!("{:2}", queue);
429            for _ in 0..remove {
430                let index = rng.gen_range(0..values.len());
431                let value = values.swap_remove(index);
432                let index = queue.iter().position(|&e| e == value).unwrap();
433                let removed = queue.remove(index);
434                assert_eq!(value, removed);
435            }
436            // print!("{:2}", queue);
437            let result: Vec<_> = queue.into_iter().collect();
438            values.sort();
439            assert_eq!(values, result);
440        }
441    }
442
443    #[test]
444    fn retain() {
445        use rand::{Rng, SeedableRng, rngs::SmallRng};
446        let mut rng = SmallRng::seed_from_u64(340712856);
447        for _i in 0..100 {
448            let len = rng.gen_range(0..128);
449            let factor = rng.gen_range(1..6);
450            // println!("round {}/10: len = {}, factor = {}", i + 1, len, factor);
451            let mut values = Vec::with_capacity(len);
452            for _ in 0..len {
453                values.push(rng.gen_range(0..100));
454            }
455            let mut queue: PrioQueue<_> = values.iter().copied().collect();
456            // print!("{:2}", queue);
457            queue.retain(|&e| e % factor != 0);
458            values.retain(|&e| e % factor != 0);
459            // print!("{:2}", queue);
460            let result: Vec<_> = queue.into_iter().collect();
461            values.sort();
462            assert_eq!(values, result);
463        }
464    }
465
466    #[test]
467    #[should_panic]
468    fn checked_bad_mut() {
469        let mut queue = PrioQueue::new(|l, r| l < r);
470        queue.push(1);
471        queue.checked_mut().push(0);
472    }
473
474    #[test]
475    fn unchecked_bad_mut() {
476        use rand::{Rng, SeedableRng, rngs::SmallRng};
477        use std::ops::RangeInclusive;
478
479        fn test(len: usize, values: RangeInclusive<i32>, remove: usize, mut rng: impl Rng) {
480            assert!(remove <= len);
481            let mut vec = Vec::with_capacity(len);
482            for _ in 0..len {
483                vec.push(rng.gen_range(values.clone()));
484            }
485            let mut queue: PrioQueue<_> = vec.iter().copied().collect();
486            let mut removed = {
487                let tmp = queue.unchecked_mut();
488                let mut removed = Vec::with_capacity(remove);
489                for _ in 0..remove {
490                    removed.push(tmp.remove(rng.gen_range(0..tmp.len())));
491                }
492                removed
493            };
494            assert_eq!(removed.len(), remove);
495            assert_eq!(queue.len(), len - remove);
496            removed.extend(queue);
497            removed.sort();
498            vec.sort();
499            assert_eq!(removed, vec);
500        }
501        let mut rng = SmallRng::seed_from_u64(150738);
502        for _i in 0..100 {
503            let len = rng.gen_range(0..100);
504            test(len, 0..=rng.gen_range(0..100), rng.gen_range(0..=len), &mut rng);
505        }
506    }
507}