排序算法 | 时间复杂度(平均) | 时间复杂度(最坏) | 时间复杂度(最好) | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O ( n 2 ) O(n^{2}) O(n2) | O ( n 2 ) O(n^{2}) O(n2) | O ( n ) O(n) O(n) | O ( 1 ) O(1) O(1) | 稳定 |
选择排序 | O ( n 2 ) O(n^{2}) O(n2) | O ( n 2 ) O(n^{2}) O(n2) | O ( n 2 ) O(n^{2}) O(n2) | O ( 1 ) O(1) O(1) | 不稳定 |
插入排序 | O ( n 2 ) O(n^{2}) O(n2) | O ( n 2 ) O(n^{2}) O(n2) | O ( n ) O(n) O(n) | O ( 1 ) O(1) O(1) | 稳定 |
希尔排序 | O ( n 1.3 ) O(n^{1.3}) O(n1.3) | O ( n 2 ) O(n^{2}) O(n2) | O ( n ) O(n) O(n) | O ( 1 ) O(1) O(1) | 不稳定 |
归并排序 | O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) | O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) | O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) | O ( n ) O(n) O(n) | 稳定 |
快速排序 | O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) | O ( n 2 ) O(n^{2}) O(n2) | O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) | O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) | 不稳定 |
堆排序 | O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) | O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) | O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) | O ( 1 ) O(1) O(1) | 不稳定 |
计数排序 | O ( n + k ) O(n+k) O(n+k) | O ( n + k ) O(n+k) O(n+k) | O ( n + k ) O(n+k) O(n+k) | O ( n + k ) O(n+k) O(n+k) | 稳定 |
基数排序 | O ( n ∗ k ) O(n*k) O(n∗k) | O ( n ∗ k ) O(n*k) O(n∗k) | O ( n ∗ k ) O(n*k) O(n∗k) | O ( n + k ) O(n+k) O(n+k) | 稳定 |
桶排序 | O ( n + k ) O(n+k) O(n+k) | O ( n 2 ) O(n^{2}) O(n2) | O ( n ) O(n) O(n) | O ( n + k ) O(n+k) O(n+k) | 稳定 |
冒泡排序
void BubbleSort(int* arr, int arrayLength)
{
cout << "Bubble Sort:" << endl;
for (int i = 1; i < arrayLength; i++) {
for (int j = 0; j < arrayLength - i; j++) {
if (arr[j] > arr[j + 1]) {
swap(arr[j], arr[j + 1]);
}
}
}
Display(arr, arrayLength);
}
选择排序
/*
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,
然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
以此类推,直到所有元素均排序完毕。
*/
void SelectSort(int* arr, int arrayLength)
{
cout << "Select Sort:" << endl;
for (int i = 0; i < arrayLength - 1; ++i) {
int minIndex = i;
for (int j = i + 1; j < arrayLength; ++j) {
if (arr[minIndex] > arr[j]) {
minIndex = j;
}
}
if (minIndex != i) {
swap(arr[i], arr[minIndex]);
}
}
Display(arr, arrayLength);
}
插入排序
/*
构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入
*/
void InsertSort(int* arr, int arrayLength)
{
cout << "Insert Sort:" << endl;
for (int i = 1; i < arrayLength; ++i) {
for (int j = i; j > 0; --j) {
if (arr[j - 1] > arr[j]) {
swap(arr[j - 1], arr[j]);
}
else {
break;
}
}
}
Display(arr, arrayLength);
}
希尔排序
/*
与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序
*/
void ShellSort(int* arr, int arrayLength, int step = 1)
{
cout << "Shell Sort:" << endl;
while (step >= 1) {
for (int i = step; i < arrayLength; i++) {
for (int j = i; j >= step; j -= step) {
if (arr[j - step] > arr[j]) {
swap(arr[j - step], arr[j]);
}
else {
break;
}
}
}
step /= 2;
}
Display(arr, arrayLength);
}
归并排序
/*
将已有序的子序列合并,得到完全有序的序列;
即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
*/
void _MergeSort(int* arr, int first, int last, int* temp)
{
int mid = (first + last) / 2;
auto mergeArray = [=]()->void {
int k = 0;
int i = first, m = mid;
int j = mid + 1, n = last;
while (i <= m && j <= n) {
temp[k++] = arr[i] < arr[j] ? arr[i++] : arr[j++];
}
while (i <= m) {
temp[k++] = arr[i++];
}
while (j <= n) {
temp[k++] = arr[j++];
}
for (i = 0; i < k; ++i) {
arr[first + i] = temp[i];
}
};
if (first < last) {
_MergeSort(arr, first, mid, temp);
_MergeSort(arr, mid + 1, last, temp);
mergeArray();
}
}
void MergeSort(int* arr, int arrayLength)
{
cout << "Merge Sort:" << endl;
int* temp = new int[arrayLength];
_MergeSort(arr, 0, arrayLength - 1, temp);
delete temp;
Display(arr, arrayLength);
}
快速排序
/*
通过一趟排序将待排记录分隔成独立的两部分,
其中一部分记录的关键字均比另一部分的关键字小,
则可分别对这两部分记录继续进行排序,以达到整个序列有序。
*/
void _QuickSort(int* arr, int left, int right)
{
auto partition = [=]()->int {
int key = arr[right];
int i = left;
for (int m = left; m < right; ++m) {
if (arr[m] <= key) {
swap(arr[i++], arr[m]);
}
}
swap(arr[i], arr[right]);
return i;
};
if (left < right) {
int p = partition();
_QuickSort(arr, left, p - 1);
_QuickSort(arr, p + 1, right);
}
}
void QuickSort(int* arr, int arrayLength)
{
cout << "Quick Sort" << endl;
_QuickSort(arr, 0, arrayLength - 1);
Display(arr, arrayLength);
}
双路快排
void _QuickSort2Ways(int* arr, int left, int right)
{
auto partition = [=]()->int {
int key = arr[left];
int i = left;
int j = right;
while (i < j) {
// j一直左移到小于key的位置
while (i < j && arr[j] >= key) {
--j;
}
if (i < j) {
arr[i] = arr[j];
++i;
}
// i一直右移到大于key的位置
while (i < j && arr[i] <= key) {
++i;
}
if (i < j) {
arr[j] = arr[i];
--j;
}
}
arr[i] = key;
return i;
};
if (left < right) {
int p = partition();
_QuickSort2Ways(arr, left, p - 1);
_QuickSort2Ways(arr, p + 1, right);
}
}
void QuickSort2Ways(int* arr, int arrayLenght)
{
cout << "Quick Sort Two Ways" << endl;
_QuickSort2Ways(arr, 0, arrayLenght - 1);
Display(arr, arrayLenght);
}
堆排序
/*
近似完全二叉树的结构,并同时满足堆积的性质:
即子结点的键值或索引总是小于(或者大于)它的父节点
*/
void HeapSort(int* arr, int arrayLength)
{
cout << "Heap Sort" << endl;
auto maxHeapify = [=](int first, int last)->void {
int root = first;
int child = root * 2 + 1;
while (child <= last) {
//比较左右孩子
if (child < last && arr[child] < arr[child + 1]) {
++child;
}
if (arr[root] >= arr[child]) {
return;
}
swap(arr[child], arr[root]);
root = child;
child = root * 2 + 1;
}
};
for (int i = arrayLength / 2 - 1; i >= 0; --i) {
maxHeapify(i, arrayLength - 1);
}
// 最大值与末尾元素交换
for (int i = arrayLength - 1; i > 0; --i) {
swap(arr[0], arr[i]);
maxHeapify(0, i - 1);
}
Display(arr, arrayLength);
}
计数排序
/*
计数排序不是基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间
*/
void CountingSort(int* arr, int arrayLength)
{
cout << "Counting Sort" << endl;
int* arr2 = new int[arrayLength];
int min = arr[0];
int max = arr[0];
for (int i = 0; i < arrayLength; i++) {
if (min > arr[i]) { min = arr[i]; }
if (max < arr[i]) { max = arr[i]; }
}
int countLength = max - min + 1;
int* countArray = new int[countLength];
memset(countArray, 0, countLength * sizeof(int));
for (int i = 0; i < arrayLength; i++) {
countArray[arr[i] - min]++;
}
for (int i = 1; i < countLength; i++) {
countArray[i] += countArray[i - 1];
}
for (int i = arrayLength - 1; i >= 0; i--) {
arr2[countArray[arr[i] - min] - 1] = arr[i];
countArray[arr[i] - min]--;
}
Display(arr2, arrayLength);
delete[] countArray;
delete[] arr2;
}
基数排序
/*
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;
依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。
最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。
*/
void RadixSort(int* arr, int arrayLength, int System = 10)
{
cout << "Radix Sort" << endl;
int* arr2 = new int[arrayLength];
int* countArray = new int[System];
int max = arr[0];
for (int i = 0; i < arrayLength; ++i) {
if (max < arr[i]) { max = arr[i]; }
}
for (int radix = 1; radix <= max; radix *= System) {
memset(countArray, 0, System * sizeof(int));
for (int i = 0; i < arrayLength; ++i) {
countArray[(arr[i] / radix) % System]++;
}
for (int i = 1; i < System; ++i) {
countArray[i] += countArray[i - 1];
}
for (int i = arrayLength - 1; i >= 0; --i) {
int temp = (arr[i] / radix) % System;
arr2[countArray[temp] - 1] = arr[i];
countArray[temp]--;
}
memcpy(arr, arr2, arrayLength * sizeof(int));
}
Display(arr, arrayLength);
delete[] arr2;
delete[] countArray;
}
桶排序
/*
当输入的元素是n个0到k之间的整数时,时间复杂度是O(n+k),空间复杂度也是O(n+k),
其排序速度快于任何比较排序算法。当k不是很大并且序列比较集中时,计数排序是一个很有效的排序算法。
*/
void _MergeSort(int* arr, int first, int last, int* temp)
{
int mid = (first + last) / 2;
auto mergeArray = [=]()->void {
int k = 0;
int i = first, m = mid;
int j = mid + 1, n = last;
while (i <= m && j <= n) {
temp[k++] = arr[i] < arr[j] ? arr[i++] : arr[j++];
}
while (i <= m) {
temp[k++] = arr[i++];
}
while (j <= n) {
temp[k++] = arr[j++];
}
for (i = 0; i < k; ++i) {
arr[first + i] = temp[i];
}
};
if (first < last) {
_MergeSort(arr, first, mid, temp);
_MergeSort(arr, mid + 1, last, temp);
mergeArray();
}
}
void BucketSort(int* arr, int arrayLength, int System = 3)
{
cout << "Bucket Sort" << endl;
int* arr2 = new int[arrayLength];
int* countArray = new int[System];
int min = arr[0];
int max = arr[0];
for (int i = 0; i < arrayLength; i++) {
if (min > arr[i]) { min = arr[i]; }
if (max < arr[i]) { max = arr[i]; }
}
int step = (max - min + 1) / System;
if (step <= 0) {
step = 1;
System = 1;
}
memset(countArray, 0, System * sizeof(int));
for (int i = 0; i < arrayLength; ++i) {
int index = (arr[i] - min) / step;
index = index < System ? index : System - 1;
countArray[index]++;
}
for (int i = 1; i < System; ++i) {
countArray[i] += countArray[i - 1];
}
for (int i = arrayLength - 1; i >= 0; --i) {
int index = (arr[i] - min) / step;
index = index < System ? index : System - 1;
arr2[countArray[index] - 1] = arr[i];
countArray[index]--;
}
memcpy(arr, arr2, arrayLength * sizeof(int));
for (int i = 0; i < System; ++i) {
int first = countArray[i];
int last = i == System - 1 ? arrayLength - 1 : countArray[i + 1];
_MergeSort(arr, first, last, arr2);
}
Display(arr, arrayLength);
delete[] arr2;
delete[] countArray;
}
主函数
#include <iostream>
#include <string.h>
using namespace std;
void Display(int* arr, int arrayLength)
{
for (int i = 0; i < arrayLength; ++i) {
cout << arr[i] << " ";
}
cout << endl;
}
int main()
{
int arr[] = { 3,2,1,1,2,5,6,4 };
int arrayLength = sizeof(arr) / sizeof(int);
cout << "initial array:" << endl;
Display(arr, arrayLength);
BubbleSort(arr, arrayLength); // 冒泡排序
SelectSort(arr, arrayLength); // 选择排序
InsertSort(arr, arrayLength); // 插入排序
ShellSort(arr, arrayLength, arrayLength); // 希尔排序
MergeSort(arr, arrayLength); // 归并排序
QuickSort(arr, arrayLength); // 快速排序
QuickSort2Ways(arr, arrayLength); // 双路快速排序
HeapSort(arr, arrayLength); // 堆排序
CountingSort(arr, arrayLength); // 计数排序
RadixSort(arr, arrayLength); // 基数排序
BucketSort(arr, arrayLength); // 桶排序
return 0;
}
参考资料:https://www.cnblogs.com/onepixel/p/7674659.html