1、实现四种堆
2、简单使用10000000/ 1千万int型测试排序性能
测试结果如下:
Heap Sort Using Max Heap : 14.378 s
Heap Sort Using Min Heap : 10.443 s
Heap Sort Using Index Max Heap : 11.391 s
Heap Sort Using Index Min Heap : 11.605 s
#define _CRT_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS
#include <iostream>
#include <ctime>
#include <cassert>
#include <string>
#include <algorithm>
using namespace std;
//随机数生成
int *generateRandomArray(int n, int rangeL, int rangeR) {
assert(rangeL <= rangeR);
int *arr = new int[n];
srand((unsigned)time(NULL));
for (int i = 0; i < n; i++)
arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
return arr;
}
//排序检验
template<typename T>
bool isSorted(T arr[], int n) {
for (int i = 0; i < n - 1; i++)
if (arr[i] > arr[i + 1])
return false;
return true;
}
//时间测试
template<typename T>
void testSort(const string &sortName, void(*sort)(T[], int), T arr[], int n) {
clock_t startTime = clock();
sort(arr, n);
clock_t endTime = clock();
assert(isSorted(arr, n));
cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s" << endl;
return;
}
//数组复制
int *copyIntArray(int a[], int n) {
int *arr = new int[n];
copy(a, a + n, arr);
return arr;
}
//打印
template<typename T>
void printArray(T arr[], int n) {
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
//最大堆
template<typename T>
class MaxHeap {
private:
T *data;
int count;
int capacity;
void shiftUp(int k) {
while (k > 1 && data[k / 2] < data[k]) {
swap(data[k / 2], data[k]);
k /= 2;
}
}
void shiftDown(int k) {
while (2 * k <= count) {
int j = 2 * k;
if (j + 1 <= count && data[j + 1] > data[j]) j++;
if (data[k] >= data[j]) break;
swap(data[k], data[j]);
k = j;
}
}
public:
MaxHeap(int capacity) {
data = new T[capacity + 1];
count = 0;
this->capacity = capacity;
}
MaxHeap(T arr[], int n) {
data = new T[n + 1];
capacity = n;
for (int i = 0; i < n; i++)
data[i + 1] = arr[i];
count = n;
for (int i = count / 2; i >= 1; i--)
shiftDown(i);
}
~MaxHeap() {
delete[] data;
}
int size() {
return count;
}
bool isEmpty() {
return count == 0;
}
void insert(T item) {
assert(count + 1 <= capacity);
data[count + 1] = item;
shiftUp(count + 1);
count++;
}
T extractMax() {
assert(count > 0);
T ret = data[1];
swap(data[1], data[count]);
count--;
shiftDown(1);
return ret;
}
T getMax() {
assert(count > 0);
return data[1];
}
};
//最小堆
template<typename T>
class MinHeap {
private:
T *data;
int count;
int capacity;
void shiftUp(int k) {
while (k > 1 && data[k / 2] > data[k]) {
swap(data[k / 2], data[k]);
k /= 2;
}
}
void shiftDown(int k) {
while (2 * k <= count) {
int j = 2 * k;
if (j + 1 <= count && data[j + 1] < data[j]) j++;
if (data[k] <= data[j]) break;
swap(data[k], data[j]);
k = j;
}
}
public:
MinHeap(int capacity) {
data = new T[capacity + 1];
count = 0;
this->capacity = capacity;
}
MinHeap(T arr[], int n) {
data = new T[n + 1];
capacity = n;
for (int i = 0; i < n; i++)
data[i + 1] = arr[i];
count = n;
for (int i = count / 2; i >= 1; i--)
shiftDown(i);
}
~MinHeap() {
delete[] data;
}
int size() {
return count;
}
bool isEmpty() {
return count == 0;
}
void insert(T item) {
assert(count + 1 <= capacity);
data[count + 1] = item;
shiftUp(count + 1);
count++;
}
T extractMin() {
assert(count > 0);
T ret = data[1];
swap(data[1], data[count]);
count--;
shiftDown(1);
return ret;
}
T getMin() {
assert(count > 0);
return data[1];
}
};
//最大索引堆
template<typename T>
class IndexMaxHeap {
private:
T *data;
int *indexes;
int *reverse;
int count;
int capacity;
void shiftUp(int k) {
while (k > 1 && data[indexes[k / 2]] < data[indexes[k]]) {
swap(indexes[k / 2], indexes[k]);
reverse[indexes[k / 2]] = k / 2;
reverse[indexes[k]] = k;
k /= 2;
}
}
void shiftDown(int k) {
while (2 * k <= count) {
int j = 2 * k;
if (j + 1 <= count && data[indexes[j + 1]] > data[indexes[j]])
j += 1;
if (data[indexes[k]] >= data[indexes[j]])
break;
swap(indexes[k], indexes[j]);
reverse[indexes[k]] = k;
reverse[indexes[j]] = j;
k = j;
}
}
public:
IndexMaxHeap(int capacity) {
data = new T[capacity + 1];
indexes = new int[capacity + 1];
reverse = new int[capacity + 1];
for (int i = 0; i <= capacity; i++)
reverse[i] = 0;
count = 0;
this->capacity = capacity;
}
~IndexMaxHeap() {
delete[] data;
delete[] indexes;
delete[] reverse;
}
int size() {
return count;
}
bool isEmpty() {
return count == 0;
}
// 传入的i对用户而言,是从0索引的
void insert(int i, T item) {
assert(count + 1 <= capacity);
assert(i + 1 >= 1 && i + 1 <= capacity);
i += 1;
data[i] = item;
indexes[count + 1] = i;
reverse[i] = count + 1;
count++;
shiftUp(count);
}
T extractMax() {
assert(count > 0);
T ret = data[indexes[1]];
swap(indexes[1], indexes[count]);
reverse[indexes[count]] = 0;
reverse[indexes[1]] = 1;
count--;
shiftDown(1);
return ret;
}
int extractMaxIndex() {
assert(count > 0);
int ret = indexes[1] - 1;
swap(indexes[1], indexes[count]);
reverse[indexes[count]] = 0;
reverse[indexes[1]] = 1;
count--;
shiftDown(1);
return ret;
}
T getMax() {
assert(count > 0);
return data[indexes[1]];
}
int getMaxIndex() {
assert(count > 0);
return indexes[1] - 1;
}
bool contain(int i) {
assert(i + 1 >= 1 && i + 1 <= capacity);
return reverse[i + 1] != 0;
}
T getT(int i) {
assert(contain(i));
return data[i + 1];
}
void change(int i, T newT) {
assert(contain(i));
i += 1;
data[i] = newT;
int j = reverse[i];
shiftUp(j);
shiftDown(j);
}
};
//最小索引堆
template<typename T>
class IndexMinHeap {
private:
T *data;
int *indexes;
int *reverse;
int count;
int capacity;
void shiftUp(int k) {
while (k > 1 && data[indexes[k / 2]] > data[indexes[k]]) {
swap(indexes[k / 2], indexes[k]);
reverse[indexes[k / 2]] = k / 2;
reverse[indexes[k]] = k;
k /= 2;
}
}
void shiftDown(int k) {
while (2 * k <= count) {
int j = 2 * k;
if (j + 1 <= count && data[indexes[j]] > data[indexes[j + 1]])
j += 1;
if (data[indexes[k]] <= data[indexes[j]])
break;
swap(indexes[k], indexes[j]);
reverse[indexes[k]] = k;
reverse[indexes[j]] = j;
k = j;
}
}
public:
IndexMinHeap(int capacity) {
data = new T[capacity + 1];
indexes = new int[capacity + 1];
reverse = new int[capacity + 1];
for (int i = 0; i <= capacity; i++)
reverse[i] = 0;
count = 0;
this->capacity = capacity;
}
~IndexMinHeap() {
delete[] data;
delete[] indexes;
delete[] reverse;
}
int size() {
return count;
}
bool isEmpty() {
return count == 0;
}
void insert(int index, T item) {
assert(count + 1 <= capacity);
assert(index + 1 >= 1 && index + 1 <= capacity);
index += 1;
data[index] = item;
indexes[count + 1] = index;
reverse[index] = count + 1;
count++;
shiftUp(count);
}
T extractMin() {
assert(count > 0);
T ret = data[indexes[1]];
swap(indexes[1], indexes[count]);
reverse[indexes[count]] = 0;
reverse[indexes[1]] = 1;
count--;
shiftDown(1);
return ret;
}
int extractMinIndex() {
assert(count > 0);
int ret = indexes[1] - 1;
swap(indexes[1], indexes[count]);
reverse[indexes[count]] = 0;
reverse[indexes[1]] = 1;
count--;
shiftDown(1);
return ret;
}
T getMin() {
assert(count > 0);
return data[indexes[1]];
}
int getMinIndex() {
assert(count > 0);
return indexes[1] - 1;
}
bool contain(int index) {
return reverse[index + 1] != 0;
}
T getT(int index) {
assert(contain(index));
return data[index + 1];
}
void change(int index, T newT) {
assert(contain(index));
index += 1;
data[index] = newT;
shiftUp(reverse[index]);
shiftDown(reverse[index]);
}
};
template<typename T>
void heapSortUsingMaxHeap(T arr[], int n) {
MaxHeap<T> maxheap = MaxHeap<T>(n);
for (int i = 0; i < n; i++)
maxheap.insert(arr[i]);
for (int i = n - 1; i >= 0; i--)
arr[i] = maxheap.extractMax();
}
template<typename T>
void heapSortUsingIndexMaxHeap(T arr[], int n) {
IndexMaxHeap<T> indexMaxheap = IndexMaxHeap<T>(n);
for (int i = 0; i < n; i++)
indexMaxheap.insert(i, arr[i]);
for (int i = n - 1; i >= 0; i--)
arr[i] = indexMaxheap.extractMax();
}
template<typename T>
void heapSortUsingMinHeap(T arr[], int n) {
MinHeap<T> minheap = MinHeap<T>(n);
for (int i = 0; i < n; i++)
minheap.insert(arr[i]);
for (int i = 0; i < n; i++)
arr[i] = minheap.extractMin();
}
template<typename T>
void heapSortUsingIndexMinHeap(T arr[], int n) {
IndexMinHeap<T> indexMinheap = IndexMinHeap<T>(n);
for (int i = 0; i < n; i++)
indexMinheap.insert(i, arr[i]);
for (int i = 0; i < n; i++)
arr[i] = indexMinheap.extractMin();
}
int main() {
int n = 10000000;
cout << "Test for Random Array, size = " << n << ", random range [0, " << n << "]" << endl;
int *arr1 = generateRandomArray(n, 0, n);
testSort("Heap Sort Using Max Heap", heapSortUsingMaxHeap, arr1, n);
int *arr2 = copyIntArray(arr1, n);
testSort("Heap Sort Using Min Heap", heapSortUsingMinHeap, arr2, n);
delete[] arr2;
int *arr3 = copyIntArray(arr1, n);
testSort("Heap Sort Using Index Max Heap", heapSortUsingIndexMaxHeap, arr3, n);
delete[] arr3;
int *arr4 = copyIntArray(arr1, n);
testSort("Heap Sort Using Index Min Heap", heapSortUsingIndexMinHeap, arr4, n);
delete[] arr4;
delete[] arr1;
cout << endl;
system("pause");
return 0;
}