原理
核心思想:利用数组
- 读取原数组,建立统计数组(下标为原数组的值,值为原数组值的次数)
- 再通过统计数组重建原数组
具体步骤:
-
利用原数组元素的取值范围,如 [0, M),建立一个统计数组count[M]
-
初始化统计数组count[M]
-
count数组的下标,就是原数组的元素(元素不是正数是,需要建立元素和下标的映射)
-
count数组的值,就是原数组元素出现的次数
-
-
通过遍历count数组,重建原数组
优化——>基数排序(位图,每一位都可以存储信息)
性能
时间复杂度:O(n)【用在建表上的时间】
空间复杂度:O(n)【在原数组上合并时】,O(n * logn)【复制数组进行合并时】
缺点
- 数据范围特别大时,会有大量没用到的空间
- 数据元素不是正数时,就需要建立原数组元素和统计数组下标的映射
用途
- 要求最快时间的场景
- 要去除重复的场景
代码
输入:数组地址,数组长度
输出:升序排列的数组
count_sort.c
#include <stdlib.h>
#include <string.h>
void count_sort(int *arr, int len)
{
if (2 > len) {
return;
}
//算出arr中的最大值再申请对应大小的数组
//假设原数组数据都是正数,如果有负数需要特殊处理
int countlen = 0;
int max = arr[0];
for (int i = 0; i < len; ++i) {
if (max < arr[i]) {
max = arr[i];
}
}
countlen = max + 1;//统计数组的大小多一点
//建立统计数组
int *countArr = (int *)malloc(countlen * sizeof(int));
memset(countArr, 0, sizeof(int) * max);
//初始化统计数组
for (int i = 0; i < len; ++i) {
countArr[arr[i]]++;
}
//重建原数组
int pos = 0;
for (int i = 0; i < countlen; ++i) {
//如果统计数组的元素不为0,就将统计数组的下标写入原数组
while (countArr[i]) {
arr[pos] = i;
pos++;
countArr[i]--;
}
}
free(countArr);
countArr = NULL;
}