use crate::storage::{ArrayLayout, Capacity, Storage};
use crate::collections::vec::{Drain, Vec};
use core::fmt::{self, Debug, Formatter};
use core::iter::{FromIterator, FusedIterator};
#[allow(unused_imports)]
use core::mem::MaybeUninit;
use core::ops::{Deref, DerefMut};
pub struct BinaryHeap<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity = usize> {
a: Vec<T, S, I>,
}
pub struct PeekMut<'a, T: 'a + Ord, S: Storage<ArrayLayout<T>>, I: Capacity = usize> {
heap: &'a mut BinaryHeap<T, S, I>,
}
impl<T: Ord + Debug, S: Storage<ArrayLayout<T>>, I: Capacity> Debug for PeekMut<'_, T, S, I> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_tuple("PeekMut").field(&self.heap.peek()).finish()
}
}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> Drop for PeekMut<'_, T, S, I> {
fn drop(&mut self) {
heapify(self.heap.a.as_mut_slice(), 0);
}
}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> Deref for PeekMut<'_, T, S, I> {
type Target = T;
fn deref(&self) -> &Self::Target {
debug_assert!(!self.heap.is_empty());
unsafe { self.heap.a.get_unchecked(0) }
}
}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> DerefMut for PeekMut<'_, T, S, I> {
fn deref_mut(&mut self) -> &mut Self::Target {
debug_assert!(!self.heap.is_empty());
unsafe { self.heap.a.get_unchecked_mut(0) }
}
}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> PeekMut<'_, T, S, I> {
pub fn pop(this: PeekMut<'_, T, S, I>) -> T {
debug_assert!(!this.heap.is_empty());
if let Some(value) = this.heap.pop() {
core::mem::forget(this);
value
} else {
unreachable!()
}
}
}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> From<S> for BinaryHeap<T, S, I> {
fn from(buf: S) -> Self {
BinaryHeap { a: Vec::from(buf) }
}
}
#[inline(always)]
fn parent(i: usize) -> usize {
(i + 1) / 2 - 1
}
#[inline(always)]
fn left(i: usize) -> usize {
2 * (i + 1) - 1
}
#[inline(always)]
fn right(i: usize) -> usize {
2 * (i + 1)
}
fn heapify<T: Ord>(a: &mut [T], i: usize) {
let l = left(i);
let r = right(i);
let mut largest = if l < a.len() && a[l] > a[i] { l } else { i };
if r < a.len() && a[r] > a[largest] {
largest = r;
}
if largest != i {
a.swap(i, largest);
heapify(a, largest);
}
}
impl<T: Ord + Debug, S: Storage<ArrayLayout<T>>, I: Capacity> Debug for BinaryHeap<T, S, I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> From<Vec<T, S, I>> for BinaryHeap<T, S, I> {
fn from(mut vec: Vec<T, S, I>) -> Self {
let a = vec.as_mut_slice();
for i in (0..(a.len() / 2)).rev() {
heapify(a, i);
}
BinaryHeap { a: vec }
}
}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> BinaryHeap<T, S, I> {
#[inline]
pub fn peek(&self) -> Option<&T> {
self.a.first()
}
#[inline]
pub fn peek_mut(&mut self) -> Option<PeekMut<T, S, I>> {
if self.is_empty() {
None
} else {
Some(PeekMut { heap: self })
}
}
pub fn pop(&mut self) -> Option<T> {
if self.is_empty() {
return None;
}
let result = self.a.swap_remove(I::from_usize(0));
heapify(self.a.as_mut_slice(), 0);
Some(result)
}
#[inline]
pub fn push(&mut self, item: T) {
#[cold]
#[inline(never)]
fn assert_failed() -> ! {
panic!("binary heap is already at capacity")
}
if self.try_push(item).is_err() {
assert_failed();
}
}
pub fn try_push(&mut self, item: T) -> Result<(), T> {
self.a.try_push(item)?;
let a = self.a.as_mut_slice();
let mut i = a.len() - 1;
while i > 0 && a[parent(i)] < a[i] {
a.swap(i, parent(i));
i = parent(i);
}
Ok(())
}
#[inline]
pub fn capacity(&self) -> usize {
self.a.capacity()
}
#[inline]
pub fn len(&self) -> usize {
self.a.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.a.is_empty()
}
#[inline]
pub fn is_full(&self) -> bool {
self.a.is_full()
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.a.iter()
}
#[inline]
pub fn drain(&mut self) -> Drain<'_, T, S, I> {
self.a.drain(..)
}
#[inline]
pub fn drain_sorted(&mut self) -> DrainSorted<'_, T, S, I> {
DrainSorted { heap: self }
}
#[inline]
pub fn clear(&mut self) {
self.a.clear();
}
#[inline]
pub fn into_vec(self) -> Vec<T, S, I> {
self.a
}
pub fn into_sorted_vec(self) -> Vec<T, S, I> {
let mut result = self.into_vec();
let a = result.as_mut_slice();
for i in (1..a.len()).rev() {
a.swap(0, i);
heapify(&mut a[..i], 0);
}
result
}
pub fn into_iter_sorted(self) -> IntoIterSorted<T, S, I> {
IntoIterSorted { heap: self }
}
}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> IntoIterator for BinaryHeap<T, S, I> {
type Item = T;
type IntoIter = <Vec<T, S, I> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.a.into_iter()
}
}
impl<T1, T2: Ord, S: Storage<ArrayLayout<T2>>, I: Capacity> Extend<T1> for BinaryHeap<T2, S, I>
where
Vec<T2, S, I>: Extend<T1>,
{
fn extend<T: IntoIterator<Item = T1>>(&mut self, iter: T) {
self.a.extend(iter);
for i in (0..(self.a.len() / 2)).rev() {
heapify(self.a.as_mut_slice(), i);
}
}
}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> FromIterator<T> for BinaryHeap<T, S, I>
where
Vec<T, S, I>: FromIterator<T>,
{
fn from_iter<It: IntoIterator<Item = T>>(iter: It) -> Self {
let a = Vec::<T, S, I>::from_iter(iter);
Self::from(a)
}
}
pub struct DrainSorted<'a, T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> {
heap: &'a mut BinaryHeap<T, S, I>,
}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> Iterator for DrainSorted<'_, T, S, I> {
type Item = T;
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.len();
(size, Some(size))
}
fn next(&mut self) -> Option<Self::Item> {
self.heap.pop()
}
}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> ExactSizeIterator for DrainSorted<'_, T, S, I> {}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> FusedIterator for DrainSorted<'_, T, S, I> {}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> Drop for DrainSorted<'_, T, S, I> {
fn drop(&mut self) {
self.for_each(drop);
}
}
#[derive(Debug)]
pub struct IntoIterSorted<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> {
heap: BinaryHeap<T, S, I>,
}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> Iterator for IntoIterSorted<T, S, I> {
type Item = T;
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.heap.len();
(size, Some(size))
}
#[inline]
fn next(&mut self) -> Option<T> {
self.heap.pop()
}
}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> ExactSizeIterator for IntoIterSorted<T, S, I> {}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> FusedIterator for IntoIterSorted<T, S, I> {}
impl<T: Clone + Ord, S: Storage<ArrayLayout<T>>, I: Capacity> Clone for IntoIterSorted<T, S, I>
where
BinaryHeap<T, S, I>: Clone,
{
fn clone(&self) -> Self {
self.heap.clone().into_iter_sorted()
}
}
impl<T: Ord, S: Storage<ArrayLayout<T>>, I: Capacity> Drop for IntoIterSorted<T, S, I> {
fn drop(&mut self) {
self.for_each(drop);
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(docs_rs, doc(cfg(feature = "alloc")))]
impl<T: Copy + Ord, I: Capacity> crate::collections::AllocHeap<T, I> {
pub fn with_capacity(capacity: I) -> Self {
BinaryHeap {
a: Vec::with_capacity(capacity),
}
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(docs_rs, doc(cfg(feature = "alloc")))]
impl<T: Copy + Ord, I: Capacity> Clone for crate::collections::AllocHeap<T, I> {
fn clone(&self) -> Self {
BinaryHeap { a: self.a.clone() }
}
}
impl<T: Ord, I: Capacity, const C: usize> BinaryHeap<T, [MaybeUninit<T>; C], I> {
pub fn new() -> Self {
let a = Vec::new();
BinaryHeap { a }
}
}
impl<T: Ord, I: Capacity, const C: usize> Default for BinaryHeap<T, [MaybeUninit<T>; C], I> {
fn default() -> Self {
Self::new()
}
}
impl<T: Clone + Ord, I: Capacity, const C: usize> Clone for BinaryHeap<T, [MaybeUninit<T>; C], I> {
fn clone(&self) -> Self {
BinaryHeap { a: self.a.clone() }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn tree_traversal_utilities() {
assert_eq!(left(0), 1);
assert_eq!(right(0), 2);
assert_eq!(parent(1), 0);
assert_eq!(parent(2), 0);
for i in 1..=1000 {
let l = left(i);
let r = right(i);
assert_eq!(l + 1, r);
assert_eq!(parent(l), i);
assert_eq!(parent(r), i);
let ll = left(l);
let lr = right(l);
let rl = left(r);
let rr = right(r);
assert_eq!(ll + 1, lr);
assert_eq!(rl + 1, rr);
assert_eq!(parent(parent(ll)), i);
assert_eq!(parent(parent(lr)), i);
assert_eq!(parent(parent(rl)), i);
assert_eq!(parent(parent(rr)), i);
}
}
#[test]
fn push_and_pop_randomized_inputs() {
use rand::{rngs::SmallRng, RngCore, SeedableRng};
let mut backing_region = [core::mem::MaybeUninit::<u32>::uninit(); 32];
let mut heap = crate::collections::SliceHeap::<_>::from(&mut backing_region[..]);
let mut rng = SmallRng::from_seed(crate::test_utils::RNG_SEED);
let mut newest = 0;
for _ in 0..32 {
newest = rng.next_u32();
heap.push(newest);
}
let mut prev = u32::max_value();
for _ in 0..1000 {
let x = heap.pop().unwrap();
assert!(x <= prev || x == newest);
prev = x;
newest = rng.next_u32();
heap.push(newest);
}
}
#[test]
fn iterators_take_and_drop_correctly() {
use core::cell::RefCell;
#[derive(Clone)]
struct Droppable<'a, 'b> {
value: usize,
log: &'a RefCell<crate::collections::SliceVec<'b, usize>>,
}
impl PartialEq for Droppable<'_, '_> {
fn eq(&self, rhs: &Self) -> bool {
self.value == rhs.value
}
}
impl Eq for Droppable<'_, '_> {}
impl PartialOrd for Droppable<'_, '_> {
fn partial_cmp(&self, rhs: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(rhs))
}
}
impl Ord for Droppable<'_, '_> {
fn cmp(&self, rhs: &Self) -> core::cmp::Ordering {
self.value.cmp(&rhs.value)
}
}
impl Drop for Droppable<'_, '_> {
fn drop(&mut self) {
self.log.borrow_mut().push(self.value);
}
}
let mut backing_array = [MaybeUninit::<usize>::uninit(); 16];
let drop_log = RefCell::new(crate::collections::SliceVec::<_>::from(&mut backing_array[..]));
let mut backing_region = [
core::mem::MaybeUninit::<Droppable>::uninit(),
core::mem::MaybeUninit::<Droppable>::uninit(),
core::mem::MaybeUninit::<Droppable>::uninit(),
core::mem::MaybeUninit::<Droppable>::uninit(),
core::mem::MaybeUninit::<Droppable>::uninit(),
core::mem::MaybeUninit::<Droppable>::uninit(),
core::mem::MaybeUninit::<Droppable>::uninit(),
core::mem::MaybeUninit::<Droppable>::uninit(),
];
let mut heap = crate::collections::SliceHeap::<Droppable>::from(&mut backing_region[..]);
for i in 1..=8 {
heap.push(Droppable {
value: i,
log: &drop_log,
});
}
let mut drain_iter = heap.drain_sorted();
assert_eq!(drain_iter.next().unwrap().value, 8);
assert_eq!(drain_iter.next().unwrap().value, 7);
assert_eq!(drop_log.borrow().len(), 2);
drop(drain_iter);
assert_eq!(drop_log.borrow().len(), 8);
assert_eq!(heap.len(), 0);
for i in 1..=8 {
heap.push(Droppable {
value: i,
log: &drop_log,
});
}
let mut into_iter = heap.into_iter_sorted();
assert_eq!(into_iter.next().unwrap().value, 8);
assert_eq!(into_iter.next().unwrap().value, 7);
assert_eq!(into_iter.next().unwrap().value, 6);
assert_eq!(drop_log.borrow().len(), 11);
drop(into_iter);
assert_eq!(drop_log.borrow().len(), 16);
assert_eq!(
drop_log.borrow().as_slice(),
&[8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1]
);
}
}