计数排序(Count Sort)是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。
计数排序的思想类似于哈希表中的直接定址法,在给定的一组序列中,先找出该序列中的最大值和最小值,从而确定需要开辟多大的辅助空间,每一个数在对应的辅助空间中都有唯一的下标。
- 找出序列中最大值和最小值,开辟Max-Min+1的辅助空间
- 最小的数对应下标为0的位置,遇到一个数就给对应下标处的值+1,。
- 遍历一遍辅助空间,就可以得到有序的一组序列
void CountSort(int* array,int size)
{
assert(array);
int max = array[0];//序列中的最大值
int min = array[0];//序列中的最小值
for(int i = 0;i < size;++i)
{
if(array[i] >= max)
{
max = array[i];
}
else
{
min = array[i];
}
}
int range = max - min + 1;//需要开辟的空间大小
int* count = new int[range];
memset(count,0,sizeof(int)*range);//辅助空间初始化为0,0代表没有那个数
for(int i = 0;i < size;++i)
{
count[array[i] - min]++;//array[i]-min是将该数对应到辅助空间的下标
}
int index = 0;
for(int i = 0;i < range;++i)//遍历辅助空间
{
while(count[i]--)//下标处的数值是几,说明该数出现了几次
{
array[index++] = i + min;//将下标处的数对应回原数组
}
}
delete[] count;
}
算法分析:
计数排序是一种以空间换时间的排序算法,并且只适用于待排序列中所有的数较为集中时,比如一组序列中的数据为0 1 2 3 4 999;就得开辟1000个辅助空间。
时间复杂度
计数排序的时间度理论为O(n+k),其中k为序列中数的范围。
不过当O(k)>O(n*log(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(n*log(n)), 如归并排序,堆排序)