计数排序是非比较排序的一种,是对哈希直接定址法的变形应用,其操作步骤如下:
1.统计相同元素出现的次数。
2.根据统计结果将序列回收到原来的序列中。
拿一组重复元素较多的数组来举例子: 10 11 10 15 14 15 11 10 13 11
1.统计相同元素出现的个数
要想事统计的元素尽量的少,就应该把整个数组的最小元素和最大元素求出来,求两者的差+1
(range),再进行动态内存开辟,开辟的空间大小为sizeof(int)*range,然后遍历一遍原数组,将
每个元素的大小减去最小值,作为开辟的新数组的下标,下标对应的元素++,从而达到了统计相
同元素出现的个数的目的。
如下图:
这就达到了统计相同元素出现的个数的效果,一定要先求最大元素和最小元素,不让动态开辟的空
间可能会过大到最后内存泄漏。
2.根据统计结果将序列回收到原来的序列中。
需要用两个循环进行实现,一个循环用来遍历count数组的下标,另一个循环用来--count数组中的
元素,将其存到a数组中,切记要将count中的元素还原回来(+min),让后再存入a数组中。
如下图:
这个图把每个细节都体现的淋漓精致,所以这就是计数排序的实现,计数排序适用于一些有较多
重复元素的数组排列,会非常快,相较于之前提到的其他排序,这个排序比较特殊,他是一个非比
较排序,代码如下:
void CountSort(int* a, int n)
{
int max = 0;
int min = 0;
for (int i = 0; i < n; i++)
{
if (a[i] > max)
{
max = a[i];
}
if (a[i] < min)
{
min = a[i];
}
}
int range = max - min + 1;
//计数
int* count = (int*)malloc( sizeof(int) * range);
if (count == NULL)
{
perror("malloc fail");
return;
}
memset(count, 0, sizeof(int) * range);
for (int i = 0; i < n; i++)
{
count[a[i] - min]++;
}
//排序
int j = 0;
for (int i = 0; i < range; i++)
{
while (count[i]--)
{
a[j++] = i + min;
}
}
free(count);
}
从代码中可以看出,除了找最大和最小元素的时候存在比较(这不在计数排序的范畴里,为了节省
空间加的一段代码),其他地方都没有用到比较操作符,所以这就是非比较排序,计数排序。