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}