Heap.h
#ifndef INC_05_HEAPIFY_HEAP_H
#define INC_05_HEAPIFY_HEAP_H
#include <algorithm>
#include <cassert>
using namespace std;
template<typename Item>
class MaxHeap{
private:
Item *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 Item[capacity+1];
count = 0;
this->capacity = capacity;
}
MaxHeap(Item arr[], int n){
data = new Item[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(Item item){
assert( count + 1 <= capacity );
data[count+1] = item;
shiftUp(count+1);
count ++;
}
Item extractMax(){
assert( count > 0 );
Item ret = data[1];
swap( data[1] , data[count] );
count --;
shiftDown(1);
return ret;
}
Item getMax(){
assert( count > 0 );
return data[1];
}
};
SortTestHelper.h
#ifndef INC_05_HEAPIFY_SORTTESTHELPER_H
#define INC_05_HEAPIFY_SORTTESTHELPER_H
#include <iostream>
#include <algorithm>
#include <string>
#include <ctime>
#include <cassert>
#include <string>
using namespace std;
namespace SortTestHelper {
int *generateRandomArray(int n, int range_l, int range_r) {
int *arr = new int[n];
srand(time(NULL));
for (int i = 0; i < n; i++)
arr[i] = rand() % (range_r - range_l + 1) + range_l;
return arr;
}
int *generateNearlyOrderedArray(int n, int swapTimes){
int *arr = new int[n];
for(int i = 0 ; i < n ; i ++ )
arr[i] = i;
srand(time(NULL));
for( int i = 0 ; i < swapTimes ; i ++ ){
int posx = rand()%n;
int posy = rand()%n;
swap( arr[posx] , arr[posy] );
}
return arr;
}
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>
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();
cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s"<<endl;
assert(isSorted(arr, n));
return;
}
};
InsertionSort.h
#ifndef INC_05_HEAPIFY_INSERTIONSORT_H
#define INC_05_HEAPIFY_INSERTIONSORT_H
#include <iostream>
#include <algorithm>
using namespace std;
template<typename T>
void insertionSort(T arr[], int n){
for( int i = 1 ; i < n ; i ++ ) {
T e = arr[i];
int j;
for (j = i; j > 0 && arr[j-1] > e; j--)
arr[j] = arr[j-1];
arr[j] = e;
}
return;
}
// 对arr[l...r]范围的数组进行插入排序
template<typename T>
void insertionSort(T arr[], int l, int r){
for( int i = l+1 ; i <= r ; i ++ ) {
T e = arr[i];
int j;
for (j = i; j > l && arr[j-1] > e; j--)
arr[j] = arr[j-1];
arr[j] = e;
}
return;
}
MergeSort.h
#ifndef INC_05_HEAPIFY_MERGESORT_H
#define INC_05_HEAPIFY_MERGESORT_H
#include <iostream>
#include <algorithm>
#include "InsertionSort.h"
using namespace std;
template<typename T>
void __merge(T arr[], int l, int mid, int r){
T aux[r-l+1];
for( int i = l ; i <= r; i ++ )
aux[i-l] = arr[i];
int i = l, j = mid+1;
for( int k = l ; k <= r; k ++ ){
if( i > mid ) { arr[k] = aux[j-l]; j ++;}
else if( j > r ){ arr[k] = aux[i-l]; i ++;}
else if( aux[i-l] < aux[j-l] ){ arr[k] = aux[i-l]; i ++;}
else { arr[k] = aux[j-l]; j ++;}
}
}
template<typename T>
void __mergeSort(T arr[], int l, int r){
if( r - l <= 15 ){
insertionSort(arr, l, r);
return;
}
int mid = (l+r)/2;
__mergeSort(arr, l, mid);
__mergeSort(arr, mid+1, r);
if( arr[mid] > arr[mid+1] )
__merge(arr, l, mid, r);
}
template<typename T>
void mergeSort(T arr[], int n){
__mergeSort( arr , 0 , n-1 );
}
template <typename T>
void mergeSortBU(T arr[], int n){
for( int i = 0 ; i < n ; i += 16 )
insertionSort(arr,i,min(i+15,n-1));
for( int sz = 16; sz <= n ; sz += sz )
for( int i = 0 ; i < n - sz ; i += sz+sz )
if( arr[i+sz-1] > arr[i+sz] )
__merge(arr, i, i+sz-1, min(i+sz+sz-1,n-1) );
}
QuickSort.h
#ifndef INC_05_HEAPIFY_QUICKSORT_H
#define INC_05_HEAPIFY_QUICKSORT_H
#include <iostream>
#include <ctime>
#include <algorithm>
#include "InsertionSort.h"
using namespace std;
template <typename T>
int _partition(T arr[], int l, int r){
swap( arr[l] , arr[rand()%(r-l+1)+l] );
T v = arr[l];
int i = l+1, j = r;
while( true ){
while( i <= r && arr[i] < v )
i ++;
while( j >= l+1 && arr[j] > v )
j --;
if( i > j )
break;
swap( arr[i] , arr[j] );
i ++;
j --;
}
swap( arr[l] , arr[j]);
return j;
}
template <typename T>
void _quickSort(T arr[], int l, int r){
if( r - l <= 15 ){
insertionSort(arr,l,r);
return;
}
int p = _partition(arr, l, r);
_quickSort(arr, l, p-1 );
_quickSort(arr, p+1, r);
}
template <typename T>
void quickSort(T arr[], int n){
srand(time(NULL));
_quickSort(arr, 0, n-1);
}
template <typename T>
void __quickSort3Ways(T arr[], int l, int r){
if( r - l <= 15 ){
insertionSort(arr,l,r);
return;
}
swap( arr[l], arr[rand()%(r-l+1)+l ] );
T v = arr[l];
int lt = l; // arr[l+1...lt] < v
int gt = r + 1; // arr[gt...r] > v
int i = l+1; // arr[lt+1...i) == v
while( i < gt ){
if( arr[i] < v ){
swap( arr[i], arr[lt+1]);
i ++;
lt ++;
}
else if( arr[i] > v ){
swap( arr[i], arr[gt-1]);
gt --;
}
else{ // arr[i] == v
i ++;
}
}
swap( arr[l] , arr[lt] );
__quickSort3Ways(arr, l, lt-1);
__quickSort3Ways(arr, gt, r);
}
template <typename T>
void quickSort3Ways(T arr[], int n){
srand(time(NULL));
__quickSort3Ways( arr, 0, n-1);
}
main.cpp
#include <iostream>
#include <algorithm>
#include "Heap.h"
#include "MergeSort.h"
#include "QuickSort.h"
#include "SortTestHelper.h"
using namespace std;
template<typename T>
void heapSort2(T arr[], int n){
MaxHeap<T> maxheap = MaxHeap<T>(arr,n);
for( int i = n-1 ; i >= 0 ; i-- )
arr[i] = maxheap.extractMax();
}
template<typename T>
void heapSort1(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();
}
int main() {
int n = 1000000;
// 测试1 一般性测试
cout<<"Test for Random Array, size = "<<n<<", random range [0, "<<n<<"]"<<endl;
int* arr1 = SortTestHelper::generateRandomArray(n,0,n);
int* arr2 = SortTestHelper::copyIntArray(arr1, n);
int* arr3 = SortTestHelper::copyIntArray(arr1, n);
int* arr4 = SortTestHelper::copyIntArray(arr1, n);
int* arr5 = SortTestHelper::copyIntArray(arr1, n);
SortTestHelper::testSort("Merge Sort", mergeSort, arr1, n);
SortTestHelper::testSort("Quick Sort", quickSort, arr2, n);
SortTestHelper::testSort("Quick Sort 3 Ways", quickSort3Ways, arr3, n);
SortTestHelper::testSort("Heap Sort 1", heapSort1, arr4, n);
SortTestHelper::testSort("Heap Sort 2", heapSort2, arr5, n);
delete[] arr1;
delete[] arr2;
delete[] arr3;
delete[] arr4;
delete[] arr5;
cout<<endl;
// 测试2 测试近乎有序的数组
int swapTimes = 100;
cout<<"Test for Random Nearly Ordered Array, size = "<<n<<", swap time = "<<swapTimes<<endl;
arr1 = SortTestHelper::generateNearlyOrderedArray(n,swapTimes);
arr2 = SortTestHelper::copyIntArray(arr1, n);
arr3 = SortTestHelper::copyIntArray(arr1, n);
arr4 = SortTestHelper::copyIntArray(arr1, n);
arr5 = SortTestHelper::copyIntArray(arr1, n);
SortTestHelper::testSort("Merge Sort", mergeSort, arr1, n);
SortTestHelper::testSort("Quick Sort", quickSort, arr2, n);
SortTestHelper::testSort("Quick Sort 3 Ways", quickSort3Ways, arr3, n);
SortTestHelper::testSort("Heap Sort 1", heapSort1, arr4, n);
SortTestHelper::testSort("Heap Sort 2", heapSort2, arr5, n);
delete[] arr1;
delete[] arr2;
delete[] arr3;
delete[] arr4;
delete[] arr5;
cout<<endl;
// 测试3 测试存在包含大量相同元素的数组
cout<<"Test for Random Array, size = "<<n<<", random range [0,10]"<<endl;
arr1 = SortTestHelper::generateRandomArray(n,0,10);
arr2 = SortTestHelper::copyIntArray(arr1, n);
arr3 = SortTestHelper::copyIntArray(arr1, n);
arr4 = SortTestHelper::copyIntArray(arr1, n);
arr5 = SortTestHelper::copyIntArray(arr1, n);
SortTestHelper::testSort("Merge Sort", mergeSort, arr1, n);
SortTestHelper::testSort("Quick Sort", quickSort, arr2, n);
SortTestHelper::testSort("Quick Sort 3 Ways", quickSort3Ways, arr3, n);
SortTestHelper::testSort("Heap Sort 1", heapSort1, arr4, n);
SortTestHelper::testSort("Heap Sort 2", heapSort2, arr5, n);
delete[] arr1;
delete[] arr2;
delete[] arr3;
delete[] arr4;
delete[] arr5;
return 0;
}