Skip to content

Instantly share code, notes, and snippets.

@dermesser
Created June 2, 2019 09:10
Show Gist options
  • Save dermesser/94c31a6ff3dac231d43d84bdbd9963c4 to your computer and use it in GitHub Desktop.
Save dermesser/94c31a6ff3dac231d43d84bdbd9963c4 to your computer and use it in GitHub Desktop.
Simple, but surprisingly fast heapsort implementation
#[macro_use]
extern crate time_test;
use std::cmp::PartialOrd;
fn left(i: usize) -> usize {
2 * i + 1
}
fn right(i: usize) -> usize {
2 * i + 2
}
fn is_heap<T: PartialOrd>(v: &[T], ix: usize) -> bool {
let subs = (left(ix) >= v.len() || is_heap(v, left(ix)))
&& (right(ix) >= v.len() || is_heap(v, right(ix)));
let order = (left(ix) >= v.len() || v[left(ix)] < v[ix])
&& (right(ix) >= v.len() || v[right(ix)] < v[ix]);
subs && order
}
fn heapify<T: PartialOrd + Copy + std::fmt::Debug>(v: &mut [T], mut ix: usize) {
loop {
//assert!(is_heap(v, left(ix)) && is_heap(v, right(ix)));
let mut max = ix;
if left(ix) < v.len() && v[left(ix)] >= v[max] {
max = left(ix);
}
if right(ix) < v.len() && v[right(ix)] >= v[max] {
max = right(ix);
}
if max == ix {
break;
}
let tmp = v[ix];
v[ix] = v[max];
v[max] = tmp;
ix = max;
}
}
fn build<T: PartialOrd + Copy + std::fmt::Debug>(v: &mut [T]) {
for i in (0..(v.len() / 2)).rev() {
heapify(v, i);
}
}
fn sort<T: PartialOrd + Copy + std::fmt::Debug>(v: &mut [T]) {
for i in (1..(v.len())).rev() {
let tmp = v[i];
v[i] = v[0];
v[0] = tmp;
heapify(&mut v[0..i], 0);
//assert!(is_heap(&mut v[0..i], 0));
}
}
fn main() {
let mut v: Vec<i32> = (0..1000).rev().collect();
{
// 70 ns per element in release mode on "Intel(R) Core(TM) i5 CPU M 460 @ 2.53GHz"
time_test!("sort");
{
build(&mut v);
sort(&mut v);
}
}
println!("built {:?}", v);
println!("sorted {:?}", v);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment