各种简单排序算法模版
基于比较的排序(复杂度下界nlogn)
冒泡排序
时间复杂度 最坏O(n^2) 平均O(n^2) 最好O(n)
空间复杂度 O(1)
稳定
void bubbleSort(int *a, int n) {
for (int i = n - 1, t; i; i = t) {
t = i;
for (int j = 0; j + 1 <= i; j++)
if (a[j] > a[j + 1]) {
swap(a[j], a[j + 1]);
t = j;
}
}
}
选择排序
时间复杂度 最坏O(n^2) 平均O(n^2) 最好O(n^2)
空间复杂度 O(1)
稳定
void selectionSort(int *a, int n) {
for (int i = 0; i < n - 1; i++) {
int mini = i;
for (int j = i + 1; j < n; j++)
if (a[j] < a[mini]) mini = j;
//swap(a[mini], a[i]); //不稳定
int t = a[mini]; //稳定
for (int j = mini; j > i; j--)
a[j] = a[j - 1];
a[i] = t;
}
}
插入排序
时间复杂度 最坏O(n^2) 平均O(n^2) 最好O(n)
空间复杂度 O(1)
稳定
void insertionSort(int *a, int n) {
for (int i = 1; i < n; i++) {
int t = a[i], j;
/*for (j = i - 1; j >= 0; j--)
if (a[j] > t) a[j + 1] = a[j];
else break;*/
for (j = i - 1; j >= 0 && a[j] > t; j--)
a[j + 1] = a[j];
a[j + 1] = t;
}
}
希尔排序
时间复杂度 最坏O(n^2) 平均O(n^1.3) 最好O(n) ?
空间复杂度 O(1)
不稳定
void shellSort(int *a, int n) { //性能一般,不经常用
int gap = 1;
while (gap < n / 3) {
gap = gap * 3 + 1;
}
for (; gap; gap = gap / 3) //枚举间隔
for (int i = 0; i < gap; i++) //枚举每一组
for (int j = i + gap; j < n; j += gap) { //插入排序
int t = a[j], k;
for (k = j - gap; k >= 0 && a[k] > t; k -= gap)
a[k + gap] = a[k];
a[k + gap] = t;
}
}
归并排序
时间复杂度 最坏O(nlogn) 平均O(nlogn) 最好O(nlogn)
空间复杂度 top down vector: O(n + logn) list: O(logn)
bottom up vector: O(n) list: O(1)
稳定
void mergeSort(int *a, int l, int r) {
if (l >= r) return;
int mid = l + r >> 1;
mergeSort(a, l, mid), mergeSort(a, mid + 1, r);
int *A = a + l, *B = a + mid + 1;
int lc = mid - l + 1, lb = r - mid;
int C[lc];
memcpy(C, A, sizeof(int) * lc);
int i = 0, j = 0, k = 0;
while (k < lc && j < lb) {
if (C[k] <= B[j]) A[i++] = C[k++];
else A[i++] = B[j++];
}
while (k < lc) A[i++] = C[k++];
}
快速排序
时间复杂度 最坏O(n^2) 平均O(nlogn) 最好O(nlogn)
空间复杂度 最坏O(n) 平均O(logn) 最好O(logn)
不稳定
void qSort(int *a, int l, int r) {
if (l == r) return;
int i = l - 1, j = r + 1, p = a[l + r >> 1];
while (i < j) {
while (a[++i] < p);
while (a[--j] > p);
if (i < j) swap(a[i], a[j]);
}
qSort(a, l, j), qSort(a, j + 1, r);
}
堆排序
时间复杂度 最坏O(nlogn) 平均O(nlogn) 最好O(nlogn)
空间复杂度 递归实现O(logn) or 迭代实现O(1)
不稳定
void down(int *h, int u, int n) {
int t = u;
if (2 * u <= n && h[2 * u] > h[t]) t = 2 * u;
if (2 * u + 1 <= n && h[2 * u + 1] > h[t]) t = 2 * u + 1;
if (t != u) {
swap(h[t], h[u]);
down(h, t, n);
}
}
void heapSort(int *a, int n) {
for (int i = n / 2; i; i--) down(a, i, n);
while (n) {
swap(a[1], a[n--]);
down(a, 1, n);
}
}
不基于比较的排序
计数排序
时间复杂度、空间复杂度与有关
稳定?
void countingSort(int *a, int n) {
const int N = 100000;
int c[N] = {0};
for (int i = 0; i < n; i++) c[a[i]]++;
for (int i = 0, t = 0; i < N; i++) //0 <= a[i] <= N - 1
while (c[i]--) a[t++] = i;
}
桶排序
是一种思想。
基本思路是:
1.将待排序元素划分到不同的桶,先扫描一遍序列求出最大值maxV和最小值minV,设桶的个数为 k ,则把区间[minV, maxV]均匀划分成k个区间,每个区间就是一个桶。将序列中的元素分配到各自的桶。
2.对每个桶内的元素进行排序。可以选择任意一种排序算法。
3.将各个桶中的元素合并成一个大的有序序列。
假设数据是均匀分布的,则每个桶的元素平均个数为n/k 。假设选择用快速排序对每个桶内的元素进行排序,那么每次排序的时间复杂度为 O(n/klog(n/k)) 。总的时间复杂度为O(n) + k * O(n/klog(n/k)) = O(n + nlog(n/k)) = O(n + nlogn - nlogk) 。当 k 接近于 n 时,桶排序的时间复杂度就可近似认为是 O(n) 的。即桶越多,时间效率就越高,而桶越多,所需空间就越大。
基数排序
时间复杂度 最坏O(n) 平均O(n) 最好O(n) 但常数较大
空间复杂度 O(n) ?
稳定
void radixSort(int *a, int n) {
for (int i = 0; i < 10; i++) {
vector<int> b[10];
for (int j = 0; j < 10; j++) b[j].clear();
for (int j = 0; j < n; j++)
b[get(a[j], i)].push_back(a[j]);
for (int j = 0, l = 0; j < 10; j++)
for (int k = 0; k < b[j].size(); k++)
a[l++] = b[j][k];
}
}
如有错误还请大佬们多多指教!