#[cfg(not(feature = "no_std"))]
use std::ops::{Deref, DerefMut};
#[cfg(not(feature = "no_std"))]
macro_rules! left_child {
($parent:ident) => {
($parent << 1) + 1 as usize
};
}
#[cfg(not(feature = "no_std"))]
macro_rules! right_child {
($parent:ident) => {
($parent << 1) + 2 as usize
};
}
#[cfg(not(feature = "no_std"))]
macro_rules! parent {
($child:ident) => {
($child - 1) >> 1
};
}
#[cfg(not(feature = "no_std"))]
#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq)]
pub struct Heap<T> {
items: Vec<T>,
comparator: fn(&T, &T) -> bool,
}
#[cfg(not(feature = "no_std"))]
impl<T> Deref for Heap<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
return &self.items;
}
}
#[cfg(not(feature = "no_std"))]
impl<T> DerefMut for Heap<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
return &mut self.items;
}
}
#[cfg(not(feature = "no_std"))]
impl<T> Default for Heap<T>
where
T: PartialOrd,
{
fn default() -> Self {
return Heap {
items: Vec::default(),
comparator: |a, b| a >= b,
};
}
}
#[cfg(not(feature = "no_std"))]
impl<T> core::fmt::Display for Heap<T>
where
T: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
return write!(f, "{:?}", self.items);
}
}
#[cfg(not(feature = "no_std"))]
impl<T: PartialOrd, const N: usize> From<[T; N]> for Heap<T> {
fn from(array: [T; N]) -> Self {
let mut heap = Heap {
items: array.into(),
comparator: |a, b| a >= b,
};
heap.rebuild();
return heap;
}
}
#[cfg(not(feature = "no_std"))]
impl<T: PartialOrd> From<Vec<T>> for Heap<T> {
fn from(array: Vec<T>) -> Self {
let mut heap = Heap {
items: array,
comparator: |a, b| a >= b,
};
heap.rebuild();
return heap;
}
}
#[cfg(not(feature = "no_std"))]
impl<T> Heap<T> {
pub fn new(comparator: fn(&T, &T) -> bool) -> Self {
return Self {
items: vec![],
comparator,
};
}
pub fn new_from(vec: Vec<T>, comparator: fn(&T, &T) -> bool) -> Self {
let mut heap = Heap {
items: vec,
comparator,
};
heap.rebuild();
return heap;
}
pub fn peek(&self) -> Option<&T> {
if self.is_empty() {
return None;
}
return Some(&self[0]);
}
pub fn into_vec(self) -> Vec<T> {
return self.items;
}
pub fn len(&self) -> usize {
return self.items.len();
}
pub fn is_empty(&self) -> bool {
return self.items.is_empty();
}
fn heapify_down(&mut self, start: usize, end: usize) {
let mut better_element_index: usize = start;
if right_child!(start) <= end
&& (self.comparator)(
&self.items[right_child!(start)],
&self.items[better_element_index],
)
{
better_element_index = right_child!(start);
}
if left_child!(start) <= end
&& (self.comparator)(
&self.items[left_child!(start)],
&self.items[better_element_index],
)
{
better_element_index = left_child!(start);
}
if better_element_index != start {
self.items.swap(start, better_element_index);
self.heapify_down(better_element_index, end);
}
}
fn rebuild(&mut self) {
let mut n = self.len() / 2;
while n > 0 {
n -= 1;
self.heapify_down(n, self.len() - 1);
}
}
pub fn push(&mut self, value: T) -> () {
self.items.push(value);
let mut point: usize = self.len() - 1;
while point > 0 && (self.comparator)(&self.items[point], &self.items[parent!(point)]) {
self.items.swap(point, parent!(point));
point = parent!(point);
}
}
pub fn pop(&mut self) -> Option<T> {
if self.is_empty() {
return None;
}
if self.len() == 1 {
return Some(self.items.pop().unwrap());
}
let pop_element: T = self.items.swap_remove(0);
self.heapify_down(0, self.len() - 1);
return Some(pop_element);
}
pub fn sort(&mut self) -> () {
let len = self.len();
for i in (1..len).rev() {
self.items.swap(0, i);
self.heapify_down(0, i - 1);
}
}
pub fn clear(&mut self) -> () {
self.items.clear();
}
#[allow(unused_parens)]
pub fn comparator(&self) -> (fn(&T, &T) -> bool) {
return self.comparator;
}
pub fn as_slice(&self) -> &[T] {
return &self.items;
}
}
#[cfg(not(feature = "no_std"))]
impl<T> Heap<T> {
pub fn from_array<const N: usize>(array: [T; N], comparator: fn(&T, &T) -> bool) -> Self {
let mut heap = Heap {
items: array.into(),
comparator,
};
heap.rebuild();
return heap;
}
}
#[cfg(not(feature = "no_std"))]
#[cfg(test)]
mod heap_tests {
use super::super::super::sorting::is_sorted;
use super::Heap;
#[test]
fn comparator_test() -> () {
let a: Heap<i32> = Heap::new(|a, b| a > b);
let c = (a.comparator())(&6, &7);
assert_eq!(c, false)
}
#[test]
fn macro_test() -> () {
let mut a = 0;
let l = left_child!(a);
let r = right_child!(a);
assert_eq!(l, 1);
assert_eq!(r, 2);
a = 20;
let p = parent!(a);
assert_eq!(9, p);
}
#[test]
fn max_heap_operation() -> () {
let mut a: Heap<i32> = Heap::new(|a, b| a >= b);
a.push(60);
a.push(2);
a.push(30);
a.push(100);
let mut vec: Vec<i32> = vec![];
vec.push(100);
vec.push(60);
vec.push(30);
vec.push(2);
assert_eq!(a.items, vec);
}
#[test]
fn min_heap_operation() -> () {
let mut a: Heap<i32> = Heap::new(|a, b| a <= b);
a.push(60);
a.push(2);
a.push(30);
a.push(100);
a.push(1);
a.push(40);
let mut vec: Vec<i32> = vec![];
vec.push(1);
vec.push(2);
vec.push(30);
vec.push(100);
vec.push(60);
vec.push(40);
assert_eq!(a.items, vec);
}
#[test]
fn pop() -> () {
let mut a: Heap<i32> = Heap::new(|a, b| a >= b);
a.push(199);
a.push(0);
a.push(20);
a.push(40);
a.push(2000);
assert_eq!(a.pop().unwrap(), 2000);
let mut b = a.clone();
b.sort();
assert!(is_sorted(&b, |a, b| a <= b));
assert_eq!(a.pop().unwrap(), 199);
let mut b = a.clone();
b.sort();
assert!(is_sorted(&b, |a, b| a <= b));
}
#[test]
fn sort() -> () {
let mut a: Heap<i32> = Heap::new(|a, b| a >= b);
a.push(199);
a.push(0);
a.push(20);
a.push(40);
a.sort();
assert_eq!(a.items, [0, 20, 40, 199]);
}
}