#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <iomanip>
#include <locale>
#include <stdlib.h>
#include <time.h>
#ifdef WINDOWS
#include <Windows.h>
#endif
#ifdef _DEBUG
#define DBG(x) (x)
#else
#define DBG(x) ((void *)0)
#endif
// Since the math for a heap assumes 1-based indexing,
// this allows us to use 1-based indexing on an existing
// vector.
template <class T>
class one_based {
std::vector<T> &data;
public:
one_based(std::vector<T> &data) : data(data) {}
T &operator[](size_t index) {
return data[index-1];
}
T operator[](size_t index) const {
return data[index-1];
}
size_t size() { return data.size(); }
};
template <class T, class Cmp>
void heapify(std::vector<T> &d, Cmp cmp) {
one_based<T> data(d);
for (size_t i=2; i<=data.size(); i++)
for (size_t j=i; j>1; j/=2)
if (cmp(data[j/2], data[j]))
std::swap(data[j], data[j/2]);
else break;
}
template <class T>
void heapify(std::vector<T> &d) {
heapify(d, std::less<T>());
}
template <class T, class Cmp>
bool check_heap(std::vector<T> &d, int N, Cmp cmp) {
one_based<T> data(d);
for (int i=1; i<N/2; i++)
if (cmp(data[i], data[i*2]) || cmp(data[i], data[i*2+1])) {
std::cerr << "\nHeap corrupted\n";
return false;
}
return true;
}
template <class T>
bool check_heap(std::vector<T> &d) {
return check_heap(d, std::less<T>());
}
template <class T, class Cmp>
void sift(std::vector<T> &d, size_t max, Cmp cmp = std::less<T>()) {
one_based<T> data(d);
size_t pos2=2;
for (size_t pos1=1; pos2<max; pos1=pos2, pos2*=2) {
if (cmp(data[pos2], data[pos2+1]))
++pos2;
if (cmp(data[pos1], data[pos2]))
std::swap(data[pos1], data[pos2]);
else break;
}
}
template <class T>
void sift(std::vector<T> &d, size_t max) {
sift(d, max, std::less<T>());
}
template <class T, class Cmp>
void heap_sort(std::vector<T> &data, Cmp cmp) {
heapify(data, cmp);
DBG((check_heap(data, data.size(), cmp)));
for (size_t pos=data.size()-1; pos>1; pos--) {
std::swap(data[0], data[pos]);
sift(data, pos, cmp);
DBG((check_heap(data, pos-1, cmp)));
}
if (cmp(data[1], data[0]))
std::swap(data[0], data[1]);
}
template <class T>
void heap_sort(std::vector<T> &d) {
heap_sort(d, std::less<T>());
}
//#ifdef TEST
template <class T, class Cmp>
bool check_sorted(std::vector<T> const &data, Cmp cmp) {
bool sorted = true;
for (size_t i=0; i<data.size()-1; i++)
if (cmp(data[i+1], data[i])) {
std::cerr << "Mis-sorted: " << data[i] << " and " << data[i+1] << "\n";
sorted = false;
}
return sorted;
}
template <class T>
bool check_sorted(std::vector<T> const &data) {
return check_sorted(data, std::less<T>());
}
template <class T>
void fill_rand(std::vector<T> &data, size_t size, time_t seed) {
srand(unsigned(seed));
data.clear();
for (size_t i=0; i<size; i++)
data.push_back((T)rand());
}
#ifdef WINDOWS
class timer {
LARGE_INTEGER start;
public:
timer() { QueryPerformanceCounter(&start); }
double duration() {
LARGE_INTEGER stop;
LARGE_INTEGER freq;
QueryPerformanceCounter(&stop);
QueryPerformanceFrequency(&freq);
return double(stop.QuadPart-start.QuadPart)/freq.QuadPart;
}
};
#else
class timer {
clock_t start;
public:
timer() : start(clock()) {}
double duration() {
return double(clock() - start)/CLOCKS_PER_SEC;
}
};
#endif
int main() {
time_t seed = time(NULL);
// std::cout.imbue(std::locale("")); fails on ideone.
for (int i=2; i<12; i++) {
size_t size = (1 << i) * 1024;
std::vector<long> data;
fill_rand(data, size, seed);
timer t;
heap_sort(data, std::less<long>());
double d = t.duration();
DBG((check_sorted(data)));
std::cout << "size:" << std::setw(12) << size << " time: " << d << "\n";
}
return 0;
}
// #endif