use std::cmp::Ord;
pub struct Heap<T> {
pub values: Vec<T>,
pub is_max_heap: bool,
}
impl<T: Ord> Heap<T> {
pub fn new(is_max_heap: bool) -> Self {
Heap {
values: Vec::new(),
is_max_heap,
}
}
pub fn insert(&mut self, value: T) {
self.values.push(value);
self.sift_up(self.values.len() - 1);
}
fn sift_up(&mut self, index: usize) {
if index == 0 {
return;
}
let parent = (index - 1) / 2;
let compare_result = if self.is_max_heap {
self.values[index] > self.values[parent]
} else {
self.values[index] < self.values[parent]
};
if compare_result {
self.values.swap(index, parent);
self.sift_up(parent);
}
}
pub fn build_heap(&mut self) {
let len = self.values.len();
for i in (0..len - 1).rev() {
self.sift_down(i, len);
}
}
pub fn sift_down(&mut self, index: usize, len: usize) {
let left_child = 2 * index + 1;
let right_child = 2 * index + 2;
let mut largest_or_smallest = index;
if left_child < len {
let compare_result = if self.is_max_heap {
self.values[left_child] > self.values[largest_or_smallest]
} else {
self.values[left_child] < self.values[largest_or_smallest]
};
if compare_result {
largest_or_smallest = left_child;
}
}
if right_child < len {
let compare_result = if self.is_max_heap {
self.values[right_child] > self.values[largest_or_smallest]
} else {
self.values[right_child] < self.values[largest_or_smallest]
};
if compare_result {
largest_or_smallest = right_child;
}
}
if largest_or_smallest != index {
self.values.swap(index, largest_or_smallest);
self.sift_down(largest_or_smallest, len);
}
}
}