基本思想:
我们已经学习过其他的排序算法,插入排序,归并排序,快速排序,随机快速排序,堆排序等等。但是这些算法最快的也要O(nlgn)。如何做到线性时间的排序呢?我们常说,空间和时间代价可以转换。我们可以利用牺牲时间来获取空间,也可以牺牲空间来获取时间。计数排序就是这样一种牺牲存储空间来获取更快时间的一种方法。
定义一个数组C,C的大小为K+1,K是输入数列中的最大数M;数组A中为要排序的整数。
1.数组初始化为0;
2.将C[A[i]]++;
3.C[i]+=C[i-1];(此时,C[A[i]]表示整数在排序之后应该在数列的位置);
4.将数放入数组B的对应位置,B则表示完成排序之后的数组。
我们可以发现,这个算法花费的时间是O(k+n)为线性时间;当K太大是,此方法便不可用,因为要开辟一个足够大的数组。此外,这是一个稳定的排序。
代码实现:
#include "iostream"
#include<algorithm>
#include<stdio.h>
void Counting_sort(int *A, int *B, int k, int arry_size) {
int C[k+1],i,j,pos,value;//对于C/C++来说,这里会报错,因为无法动态的分配数组。
//要给数组指定一个确定的大小,而且还要满足初始条件。
for (i = 0; i < 100; i++) {
C[i] = 0;
}
for (i = 0; i < arry_size; i++) {
C[A[i]]++;
}
for (i = 1; i < 100; i++) {
C[i] += C[i - 1];//C[A[i]]表示整数A[i]应该在排序中的位置
}
for (i = arry_size - 1; i >= 0; i--) {//倒叙处理,主要是为了排序的稳定性
value = A[i];
pos = C[value];
B[pos - 1] = value;
C[value]--;//这一步,主要是考虑到了有相等情况。
}
}
int main() {
int A[8] = { 2, 5, 3, 0, 2, 3, 0, 3 }, B[8], i;
Counting_sort(A, B, 5, 8);
for (i = 0; i <= 7; i++)
{
printf("%d ", B[i]);
}
printf("\n");
}