目录
思想
局限性
基本思路
代码实现
特性总结
思想
思想:计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。 操作步骤:
- 统计相同元素出现次数
- 根据统计的结果将序列回收到原来的序列中
首先有一个a数组,里面都有元素,然后再创建一个count数组,把a数组里的数字当作count的下标,比如上面A数组里第一元素是2,那么我们就让count数组下标为2的位置+1,依次往后。最后把count里的数按元素个数依次打印出来,就有序了。
局限性
- 不适合分散的数据,更适合集中数据
- 不适合浮点数、字符串、结构体数据排序,只适合整数
基本思路
绝对映射:a中的数是几,count中的下标就是几。
- 但这样可能会导致很大一部分空间就浪费了
相对映射: a中的数是x,count中的下标就是x-min。所以count中,最小下标为0,最大下标为max-min
- count[ a[i]-min ]++;
- 首先先遍历a数组,找min和max
- 然后创建新数组count,数组中的元素需要全部初始化为0 (calloc)
- 再遍历原数组统计次数
- 最后一一映射回去,注意最开始我们-min,把这个数当作count的下标。那么映射回去的时候,每一个下标都要+min后再返回给原数组。
- range=max-min+1 即count中的元素个数
- while(count[j]--),j是几就循环几次。
- 注意--前后置的区别。
代码实现
void CountSort(int* a, int n)
{
int min = a[0], max = a[0];
for (int k = 1; k < n; k++)
{
if (a[k] < min)
min = a[k];
if (a[k] > max)
max = a[k];
}
int range = max - min + 1;
int* count = (int*)calloc(range, sizeof(int));
if (count == NULL)
{
printf("calloc fail\n");
return;
}
// 统计次数
for (int i = 0; i < n; i++)
{
count[a[i] - min]++;
}
// 排序
int i = 0;
for (int j = 0; j < range; j++)
{
while (count[j]--)
{
a[i++] = j + min;
}
}
}
奇妙的是,负数也可以排序。原因是我们前面在找min时,min就是负数,后面我们在统计次数化空间的时候,a[i]-min也是将最小负数放在了count数组中下标为0的位置,并不存在越界什么的。 相对映射可以解决!
特性总结
1. 计数排序在数据范围集中时,效率很高,但是适用范围及场景有限。
2. 时间复杂度:O(MAX(N,范围))
3. 空间复杂度:O(范围)