SortTestHelper.h中给出了生成随机数组以及测试和计时函数
#pragma once
#include <iostream>
#include <string>
#include <ctime>
#include <cassert>
using namespace std;
namespace SorttestHelper
{
// 生成有n个元素的随机数组,每个元素的随机范围为[rangeL, rangeR]
int* generaateRandomArray(int n, int rangeL, int rangeR)
{
int *arr = new int[n];
srand(time(NULL));
for (int i = 0; i < n; i++)
{
arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
}
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;
}
// 打印数组
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(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 << endl;
return;
}
// 拷贝一份数组
int* copyIntArray(int a[], int n)
{
int* arr = new int[n];
copy(a, a + n, arr);
return arr;
}
}
选择排序:每次选择当前子数组中最小值,放到开头。
插入排序:来自打牌中理排的方法,从后往前插入。在近乎有序数组,效率非常高,近似O(n)
归并排序:每次从中间二分,合并两个左右两边已经排好序的子数组,合并过程需要借助额外的空间。
快速排序:parition过程中得到一个标志位,标志位左边的都小于这个数,标志位右边的都大于这个数,然后递归的调用函数。
#include <iostream>
#include <algorithm>
#include "SorttestHelper.h"
using namespace std;
template<typename T>
void selectionSort(T arr[], int n)
{
for (int i = 0; i < n; i++)
{
int minIndex = i;
for (int j = i + 1; j < n; j++)
if (arr[j] < arr[minIndex])
minIndex = j;
swap(arr[i], arr[minIndex]);
}
}
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;
}
}
template<typename T>
void __merge(T arr[], int l, int mid, int r)
{
T *aux = new T[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++; }
}
delete[]aux;
}
// 递归使用归并排序,对arr[l...r]的范围进行排序
template<typename T>
void __mergeSort(T arr[], int l, int r) {
if (l >= r)
return;
int mid = (l + r) / 2;
__mergeSort(arr, l, mid);
__mergeSort(arr, mid + 1, r);
__merge(arr, l, mid, r);
}
template<typename T>
void mergeSort(T arr[], int n) {
__mergeSort(arr, 0, n - 1);
}
template<typename T>
int __partition(T arr[], int l, int r)
{
T v = arr[l];
// arr[l+1...j]<v ; arr[j+1...i)>v
int j = l;
for (int i = l + 1;i <= r; i++)
{
if (arr[i] < v)
{
swap(arr[++j], arr[i]);
}
}
swap(arr[l], arr[j]);
return j;
}
template <typename T>
void __quickSort(T arr[], int l, int r)
{
if (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)
{
__quickSort(arr, 0, n - 1);
}
int main()
{
int n = 1000000;
int *arr = SorttestHelper::generaateRandomArray(n, 0, n);
//int *arr = SorttestHelper::generateNearlyOrderedArray(n, 10);
int *arr2 = SorttestHelper::copyIntArray(arr, n);
//SorttestHelper::testSort("Selection Sort", selectionSort, arr, n);
SorttestHelper::testSort("Merge Sort", mergeSort, arr, n);
//SorttestHelper::testSort("Insertion Sort", insertionSort, arr2, n);
SorttestHelper::testSort("Quick Sort", quickSort, arr2, n);
delete[] arr;
delete[] arr2;
return 0;
}