use std::slice;
use std::default::Default;
fn is_root(x: uint) -> bool { x < 2 }
fn left(x: uint) -> uint { x & !1u }
fn parent_left(x: uint) -> uint {
debug_assert!(!is_root(x));
left((x - 2) / 2)
}
fn inteval_heap_push<T: Ord>(v: &mut [T]) {
debug_assert!(v.len() > 0);
let mut node_max = v.len() - 1;
let mut node_min = left(node_max);
if v[node_min] > v[node_max] { v.swap(node_min, node_max); }
while !is_root(node_min) {
let par_min = parent_left(node_min);
let par_max = par_min + 1;
if v[node_min] < v[par_min] {
v.swap(par_min, node_min);
} else if v[par_max] < v[node_max] {
v.swap(par_max, node_max);
} else {
return; }
debug_assert!(v[node_min] <= v[node_max]);
node_min = par_min;
node_max = par_max;
}
}
fn update_min<T: Ord>(v: &mut [T]) {
debug_assert!(v[0] <= v[1]);
let mut left = 0;
loop {
let c1 = left * 2 + 2; let c2 = left * 2 + 4; if v.len() <= c1 { return; } let ch = if v.len() <= c2 || v[c1] < v[c2] { c1 }
else { c2 };
if v[ch] < v[left] {
v.swap(ch, left);
left = ch;
let right = left + 1;
if right < v.len() {
if v[left] > v[right] { v.swap(left, right); }
}
} else {
break;
}
}
}
fn update_max<T: Ord>(v: &mut [T]) {
debug_assert!(v[0] <= v[1]);
let mut right = 1;
loop {
let c1 = right * 2 + 1; let c2 = right * 2 + 3; if v.len() <= c1 { return; } let ch = if v.len() <= c2 || v[c1] > v[c2] { c1 }
else { c2 };
if v[ch] > v[right] {
v.swap(ch, right);
right = ch;
let left = right - 1; if v[left] > v[right] { v.swap(left, right); }
} else {
break;
}
}
}
#[deriving(Clone)]
pub struct IntervalHeap<T> {
data: Vec<T>
}
impl<T: Ord> Default for IntervalHeap<T> {
#[inline]
fn default() -> IntervalHeap<T> { IntervalHeap::new() }
}
pub type Items<'a, T> = slice::Items<'a, T>;
impl<T: Ord> IntervalHeap<T> {
pub fn new() -> IntervalHeap<T> {
IntervalHeap { data: Vec::new() }
}
pub fn with_capacity(c: uint) -> IntervalHeap<T> {
IntervalHeap { data: Vec::with_capacity(c) }
}
pub fn from_vec(mut v: Vec<T>) -> IntervalHeap<T> {
for to in range(2, v.len()) {
inteval_heap_push(v.slice_to_mut(to));
}
IntervalHeap { data: v }
}
pub fn iter(&self) -> Items<T> {
self.data.iter()
}
pub fn get_min(&self) -> Option<&T> {
match self.data.len() {
0 => None,
_ => Some(&self.data[0])
}
}
pub fn get_max(&self) -> Option<&T> {
match self.data.len() {
0 => None,
1 => Some(&self.data[0]),
_ => Some(&self.data[1])
}
}
pub fn get_min_max(&self) -> Option<(&T, &T)> {
match self.data.len() {
0 => None,
1 => Some((&self.data[0],&self.data[0])),
_ => Some((&self.data[0],&self.data[1]))
}
}
pub fn capacity(&self) -> uint {
self.data.capacity()
}
pub fn reserve_exact(&mut self, additional: uint) {
self.data.reserve_exact(additional);
}
pub fn reserve(&mut self, additional: uint) {
self.data.reserve(additional);
}
pub fn shrink_to_fit(&mut self) {
self.data.shrink_to_fit()
}
pub fn pop_min(&mut self) -> Option<T> {
match self.data.len() {
0 => None,
1...2 => self.data.swap_remove(0),
_ => {
let res = self.data.swap_remove(0);
update_min(self.data.as_mut_slice());
res
}
}
}
pub fn pop_max(&mut self) -> Option<T> {
match self.data.len() {
0...2 => self.data.pop(),
_ => {
let res = self.data.swap_remove(1);
update_max(self.data.as_mut_slice());
res
}
}
}
pub fn push(&mut self, x: T) {
self.data.push(x);
inteval_heap_push(self.data.as_mut_slice());
}
pub fn into_vec(self) -> Vec<T> { self.data }
pub fn into_sorted_vec(self) -> Vec<T> {
let mut vec = self.data;
for hsize in range(2, vec.len()).rev() {
vec.swap(1, hsize);
update_max(vec.slice_to_mut(hsize));
}
vec
}
pub fn len(&self) -> uint {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn clear(&mut self) {
self.data.clear();
}
}
impl<T: Ord> FromIterator<T> for IntervalHeap<T> {
fn from_iter<Iter: Iterator<T>>(iter: Iter) -> IntervalHeap<T> {
let vec: Vec<T> = iter.collect();
IntervalHeap::from_vec(vec)
}
}
impl<T: Ord> Extend<T> for IntervalHeap<T> {
fn extend<Iter: Iterator<T>>(&mut self, mut iter: Iter) {
let (lower, _) = iter.size_hint();
self.reserve(lower);
for elem in iter {
self.push(elem);
}
}
}
#[cfg(test)]
pub fn as_slice<T>(x: &IntervalHeap<T>) -> &[T] {
x.data.as_slice()
}
#[cfg(test)]
mod test {
use std::rand::{ task_rng, Rng };
use super::{ IntervalHeap, as_slice };
fn is_interval_heap<T: Ord>(x: &[T]) -> bool {
if x.len() < 2 { return true; }
if x[1] < x[0] { return false; }
let mut ofs = 2;
while ofs < x.len() {
let ofz = ofs + (ofs + 1 < x.len()) as uint;
if x[ofz] < x[ofs] { return false; }
let parent = (ofs / 2 - 1) & !1u;
if x[ofs] < x[parent] { return false; }
if x[parent+1] < x[ofz] { return false; }
ofs += 2;
}
true
}
#[test]
fn fuzz_push_into_sorted_vec() {
let mut rng = task_rng();
let mut tmp = Vec::with_capacity(100);
for _ in range(0, 100u) {
tmp.clear();
let mut ih: IntervalHeap<u32> = IntervalHeap::from_vec(tmp);
for _ in range(0, 100u) {
ih.push(rng.next_u32());
assert!(is_interval_heap(as_slice(&ih)));
}
tmp = ih.into_sorted_vec();
for pair in tmp.windows(2) {
assert!(pair[0] <= pair[1]);
}
}
}
#[test]
fn fuzz_pop_min() {
let mut rng = task_rng();
let mut tmp = Vec::with_capacity(100);
for _ in range(0, 100u) {
tmp.clear();
let mut ih: IntervalHeap<u32> = IntervalHeap::from_vec(tmp);
for _ in range(0, 100u) {
ih.push(rng.next_u32());
}
let mut tmpx: Option<u32> = None;
loop {
let tmpy = ih.pop_min();
assert!(is_interval_heap(as_slice(&ih)));
match (tmpx, tmpy) {
(_, None) => break,
(Some(x), Some(y)) => assert!(x <= y),
_ => ()
}
tmpx = tmpy;
}
tmp = ih.into_vec();
}
}
#[test]
fn fuzz_pop_max() {
let mut rng = task_rng();
let mut tmp = Vec::with_capacity(100);
for _ in range(0, 100u) {
tmp.clear();
let mut ih: IntervalHeap<u32> = IntervalHeap::from_vec(tmp);
for _ in range(0, 100u) {
ih.push(rng.next_u32());
}
let mut tmpx: Option<u32> = None;
loop {
let tmpy = ih.pop_max();
assert!(is_interval_heap(as_slice(&ih)));
match (tmpx, tmpy) {
(_, None) => break,
(Some(x), Some(y)) => assert!(x >= y),
_ => ()
}
tmpx = tmpy;
}
tmp = ih.into_vec();
}
}
}