heapify/
lib.rs

1//! A collection of convenience functions for heapifying a slice in `rust`.
2//!
3//! # Quick Start
4//! A simple way to use `heapify` is with a `Vec<T>`.
5//! ``` rust
6//! use heapify::*;
7//! let mut vec = vec![5, 7, 9];
8//! make_heap(&mut vec);
9//!
10//! pop_heap(&mut vec);
11//! assert_eq!(vec.pop(), Some(9));
12//!
13//! pop_heap(&mut vec);
14//! assert_eq!(vec.pop(), Some(7));
15//!
16//! assert_eq!(peek_heap(&mut vec), Some(&5));
17//! ```
18
19#![warn(rust_2018_idioms)]
20use core::cmp::Ordering;
21
22/// Transforms the given slice into a maximal heap.
23///
24/// After `make_heap` is called, the maximal element of the slice is located
25/// at `slice[0]`.
26///
27/// # Examples
28///
29/// ```
30/// use heapify::*;
31/// let mut arr = [5, 7, 9];
32/// make_heap(&mut arr);
33/// assert_eq!(arr[0], 9);
34/// assert_eq!(peek_heap(&mut arr), Some(&9));
35/// ```
36pub fn make_heap<T: PartialOrd>(slice: &mut [T]) {
37    make_heap_with(slice, T::partial_cmp)
38}
39
40/// Transforms the given slice into a heap with a given predicate.
41///
42/// After `make_heap_with` is called, the top element of the heap is located
43/// at `slice[0]`.
44///
45/// # Examples
46///
47/// ```
48/// use heapify::*;
49/// let mut arr = [5, 7, 9];
50/// make_heap_with(&mut arr, |lhs, rhs| rhs.partial_cmp(lhs));
51/// assert_eq!(arr[0], 5);
52/// assert_eq!(peek_heap(&mut arr), Some(&5));
53/// ```
54pub fn make_heap_with<T>(slice: &mut [T], pred: fn(&T, &T) -> Option<Ordering>) {
55    let n = slice.len();
56    for i in (0..=((n - 1) / 2)).rev() {
57        bubble_down(slice, i, pred);
58    }
59}
60
61/// Creates a `HeapIterator<T>` from a given slice.
62///
63/// # Examples
64///
65/// ```
66/// use heapify::*;
67/// let mut arr = [5, 7, 9];
68/// let mut iter = make_heap_iter(&mut arr);
69/// assert_eq!(iter.next().cloned(), Some(9));
70/// ```
71pub fn make_heap_iter<T: PartialOrd>(slice: &mut [T]) -> HeapIterator<'_, T> {
72    make_heap(slice);
73    HeapIterator { heap: slice }
74}
75
76/// Creates a `PredHeapIterator<T>` from a given slice and a given predicate.
77///
78/// # Examples
79///
80/// ```
81/// use heapify::*;
82/// let mut arr = [5, 7, 9];
83/// let mut iter = make_heap_iter_with(&mut arr, |lhs, rhs| rhs.partial_cmp(lhs));
84/// assert_eq!(iter.next().cloned(), Some(5));
85/// ```
86pub fn make_heap_iter_with<T>(
87    slice: &mut [T],
88    pred: fn(&T, &T) -> Option<Ordering>,
89) -> PredHeapIterator<'_, T> {
90    make_heap_with(slice, pred);
91    PredHeapIterator { heap: slice, pred }
92}
93
94/// Pushes an element into a heap.
95///
96/// Given a slice where `slice[0..len-1]` is a heap, then the element at
97/// `slice[len-1]` is pushed into the heap by bubbling it up to its correct
98/// position.
99///
100/// # Examples
101///
102/// ```
103/// use heapify::*;
104/// let mut vec = vec![5, 7, 9];
105/// make_heap(&mut vec);
106/// assert_eq!(peek_heap(&mut vec), Some(&9));
107///
108/// vec.push(8);
109/// push_heap(&mut vec);
110/// assert_eq!(peek_heap(&mut vec), Some(&9));
111///
112/// vec.push(10);
113/// push_heap(&mut vec);
114/// assert_eq!(peek_heap(&mut vec), Some(&10));
115/// ```
116pub fn push_heap<T: PartialOrd>(slice: &mut [T]) {
117    bubble_up(slice, T::partial_cmp);
118}
119
120/// Pushes an element into a heap, with a given predicate.
121///
122/// Given a slice where `slice[0..len-1]` is a heap, then the element at
123/// `slice[len-1]` is pushed into the heap by bubbling it up to its correct
124/// position.
125///
126/// # Examples
127///
128/// ```
129/// use heapify::*;
130/// let mut vec = vec![5, 7, 9];
131/// make_heap_with(&mut vec, |lhs, rhs| rhs.partial_cmp(lhs));
132/// assert_eq!(peek_heap(&mut vec), Some(&5));
133///
134/// vec.push(8);
135/// push_heap_with(&mut vec, |lhs, rhs| rhs.partial_cmp(lhs));
136/// assert_eq!(peek_heap(&mut vec), Some(&5));
137///
138/// vec.push(3);
139/// push_heap_with(&mut vec, |lhs, rhs| rhs.partial_cmp(lhs));
140/// assert_eq!(peek_heap(&mut vec), Some(&3));
141/// ```
142pub fn push_heap_with<T>(slice: &mut [T], pred: fn(&T, &T) -> Option<Ordering>) {
143    bubble_up(slice, pred);
144}
145
146/// Pops an element from a maximal heap.
147///
148/// Given a heap, the maximal element at `slice[0]` is moved to `slice[len-1]`
149/// and the heap invariant is maintained for `slice[0..len-1]`.
150///
151/// # Examples
152///
153/// ```
154/// use heapify::*;
155/// let mut vec = vec![5, 7, 9];
156/// make_heap(&mut vec);
157/// assert_eq!(peek_heap(&mut vec), Some(&9));
158///
159/// pop_heap(&mut vec);
160/// assert_eq!(vec.pop(), Some(9));
161///
162/// pop_heap(&mut vec);
163/// assert_eq!(vec.pop(), Some(7));
164///
165/// pop_heap(&mut vec);
166/// assert_eq!(vec.pop(), Some(5));
167/// ```
168pub fn pop_heap<T: PartialOrd>(slice: &mut [T]) {
169    let n = slice.len();
170    if n > 1 {
171        slice.swap(0, n - 1);
172        bubble_down(&mut slice[0..n - 1], 0, T::partial_cmp);
173    }
174}
175/// Pops an element from a maximal heap, with a given predicate.
176///
177/// Given a heap, the maximal element at `slice[0]` is moved to `slice[len-1]`
178/// and the heap invariant is maintained for `slice[0..len-1]`.
179///
180/// # Examples
181///
182/// ```
183/// use heapify::*;
184/// let mut vec = vec![5, 7, 9];
185/// make_heap_with(&mut vec, |lhs, rhs| rhs.partial_cmp(lhs));
186/// assert_eq!(peek_heap(&mut vec), Some(&5));
187///
188/// pop_heap_with(&mut vec, |lhs, rhs| rhs.partial_cmp(lhs));
189/// assert_eq!(vec.pop(), Some(5));
190///
191/// pop_heap_with(&mut vec, |lhs, rhs| rhs.partial_cmp(lhs));
192/// assert_eq!(vec.pop(), Some(7));
193///
194/// pop_heap_with(&mut vec, |lhs, rhs| rhs.partial_cmp(lhs));
195/// assert_eq!(vec.pop(), Some(9));
196/// ```
197pub fn pop_heap_with<T>(slice: &mut [T], pred: fn(&T, &T) -> Option<Ordering>) {
198    let n = slice.len();
199    if n > 1 {
200        slice.swap(0, n - 1);
201        bubble_down(&mut slice[0..n - 1], 0, pred);
202    }
203}
204
205/// Safely peeks at the top element of the heap. Returns `None` if heap is
206/// empty.
207///
208/// # Examples
209///
210/// ```
211/// use heapify::peek_heap;
212/// let mut arr = [2];
213/// assert_eq!(peek_heap(&mut arr), Some(&2));
214/// let mut empty = [0; 0];
215/// assert_eq!(peek_heap(&mut empty), None);
216/// ```
217pub fn peek_heap<T>(slice: &mut [T]) -> Option<&T> {
218    let n = slice.len();
219    if n > 0 {
220        Some(&slice[0])
221    } else {
222        None
223    }
224}
225
226fn pred_greater<T>(pred: fn(&T, &T) -> Option<Ordering>, lhs: &T, rhs: &T) -> bool {
227    pred(lhs, rhs) == Some(Ordering::Greater)
228}
229
230fn bubble_up<T>(slice: &mut [T], pred: fn(&T, &T) -> Option<Ordering>) {
231    let n = slice.len();
232    let mut i = n;
233    let mut p = i / 2;
234    while p > 0 && (pred_greater(pred, &slice[i - 1], &slice[p - 1])) {
235        slice.swap(p - 1, i - 1);
236        i = p;
237        p = i / 2;
238    }
239}
240
241fn bubble_down<T>(slice: &mut [T], index: usize, pred: fn(&T, &T) -> Option<Ordering>) {
242    let n = slice.len();
243    let mut i = index;
244    let mut l = i * 2 + 1;
245    let mut r = i * 2 + 2;
246
247    if r < n && pred_greater(pred, &slice[r], &slice[l]) {
248        l = r;
249    }
250    // invariant: slice[l] >= slice[r]
251    // if slice[l] > slice[i], do push
252    while l < n && pred_greater(pred, &slice[l], &slice[i]) {
253        slice.swap(i, l);
254        i = l;
255        l = i * 2 + 1;
256        r = i * 2 + 2;
257        if r < n && pred_greater(pred, &slice[r], &slice[l]) {
258            l = r;
259        }
260    }
261}
262
263/// An iterator type to iterate upon a heap.
264///
265/// A complete iteration has the side effect of sorting the underlying
266/// slice in ascending order.
267///
268/// # Examples
269/// Basic usage:
270/// ```
271/// use heapify::*;
272/// let mut arr = [5, 7, 9];
273/// let iter = make_heap_iter(&mut arr);
274/// for item in iter {
275///     print!("{} ", item);
276/// }
277/// ```
278/// This will print:
279/// ``` text
280/// 9 7 5
281/// ```
282#[derive(Debug)]
283pub struct HeapIterator<'a, T: PartialOrd> {
284    heap: &'a mut [T],
285}
286
287impl<'a, T: PartialOrd> core::iter::Iterator for HeapIterator<'a, T> {
288    type Item = &'a mut T;
289
290    fn next(&mut self) -> Option<Self::Item> {
291        let n = self.heap.len();
292        if n > 0 {
293            pop_heap(self.heap);
294
295            unsafe {
296                let old = core::ptr::read(&self.heap);
297                let (left, right) = old.split_at_mut(n - 1);
298                core::ptr::write(&mut self.heap, left);
299                assert_eq!(right.len(), 1);
300
301                Some(&mut right[0])
302            }
303        } else {
304            None
305        }
306    }
307
308    fn size_hint(&self) -> (usize, Option<usize>) {
309        (self.heap.len(), Some(self.heap.len()))
310    }
311}
312
313/// An iterator type to iterate upon a heap with a given predicate.
314///
315/// Larger than HeapIterator due to storing of the function pointer predicate.
316///
317/// A complete iteration has the side effect of sorting the underlying
318/// slice in order provided by predicate.
319///
320/// # Examples
321/// Basic usage:
322/// ```
323/// use heapify::*;
324/// let mut arr = [5, 7, 9];
325/// let iter = make_heap_iter_with(&mut arr, |lhs, rhs| rhs.partial_cmp(lhs));
326/// for item in iter {
327///     print!("{} ", item);
328/// }
329/// ```
330/// This will print:
331/// ``` text
332/// 5 7 9
333/// ```
334pub struct PredHeapIterator<'a, T> {
335    heap: &'a mut [T],
336    pred: fn(&T, &T) -> Option<Ordering>,
337}
338
339impl<'a, T> core::iter::Iterator for PredHeapIterator<'a, T> {
340    type Item = &'a mut T;
341
342    fn next(&mut self) -> Option<Self::Item> {
343        let n = self.heap.len();
344        if n > 0 {
345            pop_heap_with(self.heap, self.pred);
346
347            unsafe {
348                let old = core::ptr::read(&self.heap);
349                let (left, right) = old.split_at_mut(n - 1);
350                core::ptr::write(&mut self.heap, left);
351                assert_eq!(right.len(), 1);
352
353                Some(&mut right[0])
354            }
355        } else {
356            None
357        }
358    }
359
360    fn size_hint(&self) -> (usize, Option<usize>) {
361        (self.heap.len(), Some(self.heap.len()))
362    }
363}
364
365#[cfg(test)]
366mod tests {
367
368    use super::*;
369
370    #[test]
371    fn test_peek_heap() {
372        let mut arr = [2];
373        assert_eq!(peek_heap(&mut arr), Some(&2));
374        let mut empty = [0; 0];
375        assert_eq!(peek_heap(&mut empty), None);
376    }
377
378    #[test]
379    fn test_make_heap() {
380        let mut arr = [5, 7, 9];
381        make_heap(&mut arr);
382        assert_eq!(arr[0], 9);
383        assert_eq!(peek_heap(&mut arr), Some(&9));
384    }
385
386    #[test]
387    fn test_make_heap_with() {
388        let mut arr = [5, 7, 9];
389        make_heap_with(&mut arr, |lhs, rhs| rhs.partial_cmp(lhs));
390        assert_eq!(arr[0], 5);
391        assert_eq!(peek_heap(&mut arr), Some(&5));
392    }
393
394    #[test]
395    fn test_push_heap() {
396        let mut vec = vec![5, 7, 9];
397        make_heap(&mut vec);
398        assert_eq!(peek_heap(&mut vec), Some(&9));
399
400        vec.push(8);
401        push_heap(&mut vec);
402        assert_eq!(peek_heap(&mut vec), Some(&9));
403
404        vec.push(10);
405        push_heap(&mut vec);
406        assert_eq!(peek_heap(&mut vec), Some(&10));
407    }
408
409    #[test]
410    fn test_push_heap_with() {
411        let mut vec = vec![5, 7, 9];
412        let pred: fn(&i32, &i32) -> Option<Ordering> = |lhs, rhs| rhs.partial_cmp(lhs);
413        make_heap_with(&mut vec, pred);
414        assert_eq!(peek_heap(&mut vec), Some(&5));
415
416        vec.push(8);
417        push_heap_with(&mut vec, pred);
418        assert_eq!(peek_heap(&mut vec), Some(&5));
419
420        vec.push(3);
421        push_heap_with(&mut vec, pred);
422        assert_eq!(peek_heap(&mut vec), Some(&3));
423    }
424
425    #[test]
426    fn test_pop_heap() {
427        let mut vec = vec![5, 7, 9];
428        make_heap(&mut vec);
429        assert_eq!(peek_heap(&mut vec), Some(&9));
430
431        pop_heap(&mut vec);
432        assert_eq!(vec.pop(), Some(9));
433
434        pop_heap(&mut vec);
435        assert_eq!(vec.pop(), Some(7));
436
437        pop_heap(&mut vec);
438        assert_eq!(vec.pop(), Some(5));
439    }
440
441    #[test]
442    fn test_pop_heap_with() {
443        let mut vec = vec![5, 7, 9];
444        let pred: fn(&i32, &i32) -> Option<Ordering> = |lhs, rhs| rhs.partial_cmp(lhs);
445        make_heap_with(&mut vec, pred);
446        assert_eq!(peek_heap(&mut vec), Some(&5));
447
448        pop_heap_with(&mut vec, pred);
449        assert_eq!(vec.pop(), Some(5));
450
451        pop_heap_with(&mut vec, pred);
452        assert_eq!(vec.pop(), Some(7));
453
454        pop_heap_with(&mut vec, pred);
455        assert_eq!(vec.pop(), Some(9));
456    }
457
458    #[test]
459    fn test_heap_iterator_next_value() {
460        let mut vec = vec![5, 7, 9];
461        let mut iter = make_heap_iter(&mut vec);
462
463        assert_eq!(iter.next().cloned(), Some(9));
464        assert_eq!(iter.next().cloned(), Some(7));
465        assert_eq!(iter.next().cloned(), Some(5));
466    }
467
468    #[test]
469    fn test_heap_iterator_sorted() {
470        let mut vec = vec![1, 9, 2, 8, 3, 7];
471        let iter = make_heap_iter(&mut vec);
472        for _ in iter {}
473        assert_eq!(vec, vec![1, 2, 3, 7, 8, 9]);
474    }
475
476    #[test]
477    fn test_heap_iterator_mut() {
478        let mut vec = vec![1, 2, 3, 4, 5, 6];
479        let iter = make_heap_iter(&mut vec);
480        iter.for_each(|i| {
481            if *i % 2 == 0 {
482                *i = 0
483            }
484        });
485
486        assert_eq!(vec, vec![1, 0, 3, 0, 5, 0]);
487    }
488
489    #[test]
490    fn test_pred_heap_iterator_sorted() {
491        let pred: fn(&i32, &i32) -> Option<Ordering> = |lhs, rhs| rhs.partial_cmp(lhs);
492        let mut vec = vec![1, 9, 2, 8, 3, 7];
493        let iter = make_heap_iter_with(&mut vec, pred);
494        for _ in iter {}
495        assert_eq!(vec, vec![9, 8, 7, 3, 2, 1]);
496    }
497
498    #[test]
499    fn test_pred_heap_iterator_mut() {
500        let pred: fn(&i32, &i32) -> Option<Ordering> = |lhs, rhs| rhs.partial_cmp(lhs);
501        let mut vec = vec![1, 2, 3, 4, 5, 6];
502        let iter = make_heap_iter_with(&mut vec, pred);
503        iter.for_each(|i| {
504            if *i % 2 == 1 {
505                *i = 0
506            }
507        });
508
509        assert_eq!(vec, vec![6, 0, 4, 0, 2, 0]);
510    }
511}