binomial_heap/
lib.rs

1//! A priority queue based on a [binomial heap].
2//!
3//! See [`BinomialHeap`](struct.BinomialHeap.html) for details.
4//!
5//! [binomial heap]: https://en.wikipedia.org/wiki/Binomial_heap
6
7#![deny(missing_docs)]
8
9use std::fmt::{self, Debug};
10use std::marker::PhantomData;
11use std::mem;
12
13mod node;
14
15pub use node::{IntoIter, Iter};
16
17/// A priority queue based on a binomial heap.
18///
19/// Like [`BinaryHeap`], `BionmialHeap` is an implementation of a priority queue. Unlike
20/// `BinaryHeap`, `BionmialHeap` provides an efficient `append` method, at the cost of greater
21/// memory usage, slower iteration, and poor cache locality.
22///
23/// # Time Complexity
24///
25/// | Operation                      | Time Complexity        |
26/// |--------------------------------|------------------------|
27/// | [`append`](#method.append)     | `O(log n)` (amortized) |
28/// | [`peek`](#method.peek)         | `O(log n)`             |
29/// | [`pop`](#method.pop)           | `O(log n)`             |
30/// | [`push`](#method.push)         | `O(1)` (amortized)     |
31/// | [`push_pop`](#method.push_pop) | `O(log n)`             |
32/// | [`replace`](#method.replace)   | `O(log n)`             |
33///
34/// [`BinaryHeap`]: https://doc.rust-lang.org/std/collections/struct.BinaryHeap.html
35#[derive(Clone)]
36pub struct BinomialHeap<T: Ord> {
37    root: Option<Box<node::Node<T>>>,
38    len: usize,
39}
40
41impl<T: Ord> BinomialHeap<T> {
42    /// Returns a new heap.
43    pub fn new() -> Self {
44        BinomialHeap { root: None, len: 0 }
45    }
46
47    /// Checks if the heap is empty.
48    pub fn is_empty(&self) -> bool {
49        self.root.is_none()
50    }
51
52    /// Returns the number of items in the heap.
53    pub fn len(&self) -> usize {
54        self.len
55    }
56
57    /// Returns an iterator that yields references to the items in the heap in arbitrary order.
58    pub fn iter(&self) -> Iter<T> {
59        node::iter(&self.root, self.len)
60    }
61
62    /// Returns a reference to the greatest item in the heap.
63    ///
64    /// Returns `None` if the heap is empty.
65    pub fn peek(&self) -> Option<&T> {
66        node::peek(&self.root)
67    }
68
69    /// Pushes the given item onto the heap.
70    pub fn push(&mut self, item: T) {
71        node::push(&mut self.root, item);
72        self.len += 1;
73    }
74
75    /// Moves the given heap's items into the heap, leaving the given heap empty.
76    ///
77    /// This is equivalent to, but likely to be faster than, the following:
78    ///
79    /// ```
80    /// # let mut heap = binomial_heap::BinomialHeap::<i32>::new();
81    /// # let mut heap2 = binomial_heap::BinomialHeap::<i32>::new();
82    /// heap.extend(heap2.drain());
83    /// ```
84    pub fn append(&mut self, other: &mut Self) {
85        match self.root {
86            None => mem::swap(self, other),
87            Some(ref mut root) => {
88                node::append(root, other.root.take());
89                self.len += mem::replace(&mut other.len, 0);
90            }
91        }
92    }
93
94    /// Pushes the given item onto the heap, then removes the greatest item in the heap and returns
95    /// it.
96    ///
97    /// This method is equivalent to, but likely faster than, the following:
98    ///
99    /// ```
100    /// # let mut heap = binomial_heap::BinomialHeap::new();
101    /// # let item = 0;
102    /// heap.push(item);
103    /// let max = heap.pop().unwrap();
104    /// ```
105    pub fn push_pop(&mut self, item: T) -> T {
106        self.push(item);
107        self.pop().expect("heap was empty")
108    }
109
110    /// Removes the greatest item in the heap, then pushes the given item onto the heap.
111    ///
112    /// Returns the item that was removed, or `None` if the heap was empty.
113    ///
114    /// This method is equivalent to, but likely faster than, the following:
115    ///
116    /// ```
117    /// # let mut heap = binomial_heap::BinomialHeap::new();
118    /// # let item = 0;
119    /// let max = heap.pop();
120    /// heap.push(item);
121    /// ```
122    pub fn replace(&mut self, item: T) -> Option<T> {
123        let max = self.pop();
124        self.push(item);
125        max
126    }
127
128    /// Removes the greatest item in the heap and returns it.
129    ///
130    /// Returns `None` if the heap was empty.
131    ///
132    /// If a call to this method is immediately preceded by a call to [`push`], consider using
133    /// [`push_pop`] instead. If a call to this method is immediately followed by a call to
134    /// [`push`], consider using [`replace`] instead.
135    ///
136    /// [`push`]: #method.push
137    /// [`push_pop`]: #method.push_pop
138    /// [`replace`]: #method.replace
139    pub fn pop(&mut self) -> Option<T> {
140        node::pop(&mut self.root, &mut self.len)
141    }
142
143    /// Removes all items from the heap.
144    pub fn clear(&mut self) {
145        *self = Self::new();
146    }
147
148    /// Removes all items from the heap and returns an iterator that yields them in arbitrary
149    /// order.
150    ///
151    /// All items are removed even if the iterator is not exhausted. However, the behavior of
152    /// this method is unspecified if the iterator is leaked (e.g. via [`mem::forget`]).
153    ///
154    /// [`mem::forget`]: https://doc.rust-lang.org/std/mem/fn.forget.html
155    pub fn drain(&mut self) -> Drain<T> {
156        Drain { iter: mem::replace(self, Self::new()).into_iter(), marker: PhantomData }
157    }
158}
159
160impl<T: Ord + Debug> Debug for BinomialHeap<T> {
161    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
162        f.debug_list().entries(self).finish()
163    }
164}
165
166impl<T: Ord> Default for BinomialHeap<T> {
167    fn default() -> Self {
168        Self::new()
169    }
170}
171
172impl<T: Ord> Extend<T> for BinomialHeap<T> {
173    fn extend<I: IntoIterator<Item = T>>(&mut self, items: I) {
174        for item in items { self.push(item); }
175    }
176}
177
178impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinomialHeap<T> {
179    fn extend<I: IntoIterator<Item = &'a T>>(&mut self, items: I) {
180        for item in items { self.push(*item); }
181    }
182}
183
184impl<T: Ord> std::iter::FromIterator<T> for BinomialHeap<T> {
185    fn from_iter<I: IntoIterator<Item = T>>(items: I) -> Self {
186        let mut heap = Self::new();
187        heap.extend(items);
188        heap
189    }
190}
191
192impl<'a, T: 'a + Ord + Copy> std::iter::FromIterator<&'a T> for BinomialHeap<T> {
193    fn from_iter<I: IntoIterator<Item = &'a T>>(items: I) -> Self {
194        let mut heap = Self::new();
195        heap.extend(items);
196        heap
197    }
198}
199
200impl<T: Ord> IntoIterator for BinomialHeap<T> {
201    type Item = T;
202    type IntoIter = IntoIter<T>;
203
204    fn into_iter(self) -> IntoIter<T> {
205        node::into_iter(self.root, self.len)
206    }
207}
208
209impl<'a, T: Ord> IntoIterator for &'a BinomialHeap<T> {
210    type Item = &'a T;
211    type IntoIter = Iter<'a, T>;
212
213    fn into_iter(self) -> Iter<'a, T> {
214        self.iter()
215    }
216}
217
218/// An iterator that drains a `BinomialHeap`, yielding its items in arbitrary order.
219///
220/// Acquire through [`BinomialHeap::drain`](struct.BinomialHeap.html#method.drain).
221pub struct Drain<'a, T: 'a> {
222    iter: IntoIter<T>,
223    marker: PhantomData<&'a mut IntoIter<T>>,
224}
225
226impl<'a, T: Ord> Iterator for Drain<'a, T> {
227    type Item = T;
228
229    fn next(&mut self) -> Option<T> {
230        self.iter.next()
231    }
232
233    fn size_hint(&self) -> (usize, Option<usize>) {
234        self.iter.size_hint()
235    }
236}
237
238impl<'a, T: Ord> ExactSizeIterator for Drain<'a, T> {
239    fn len(&self) -> usize {
240        self.iter.len()
241    }
242}
243
244#[allow(dead_code)]
245fn assert_covariance() {
246    fn heap<'a, T: Ord>(heap: BinomialHeap<&'static T>) -> BinomialHeap<&'a T> {
247        heap
248    }
249
250    fn into_iter<'a, T: Ord>(iter: IntoIter<&'static T>) -> IntoIter<&'a T> {
251        iter
252    }
253
254    fn iter<'i, 'a, T: Ord>(iter: Iter<'i, &'static T>) -> Iter<'i, &'a T> {
255        iter
256    }
257}