适用范围:数字重复出现比较多,分布区间小
1.遍历找到最大值最小值确定区间
int nMax=arr[0];//最大值
int nMin=arr[0];//最小值
//遍历数组得到数组的最大值和最小值
for (int i = 1; i < len; i++) {
if (arr[i] > nMax) nMax = arr[i];
if (arr[i] < nMin)nMin = arr[i];
}
2.申请计数器数组初值为0
//根据最大值最小值确定范围,申请数组
int nSize = nMax - nMin + 1;
int* parr = (int*)malloc(sizeof(int) * nSize);
memset(parr, 0, sizeof(int) * nSize);//初始化为0
3.对数字进行计数
for (int i = 0; i < len; i++) {
parr[arr[i]-nMin]++;//统计各个数出现的次数
}
4.将计数数组按一定方法输出就是排序后的结果
//输出结果
for (int i = 0; i < nSize; i++) {
for (int j = 0; j < parr[i]; j++)
{
printf("%d ", i + nMin);
}
}
最终程序如下:
void CountSort(int* arr, int len) {
int nMax=arr[0];//最大值
int nMin=arr[0];//最小值
//遍历数组得到数组的最大值和最小值
for (int i = 1; i < len; i++) {
if (arr[i] > nMax) nMax = arr[i];
if (arr[i] < nMin)nMin = arr[i];
}
//根据最大值最小值确定范围,申请数组
int nSize = nMax - nMin + 1;
int* parr = (int*)malloc(sizeof(int) * nSize);
memset(parr, 0, sizeof(int) * nSize);//初始化为0
for (int i = 0; i < len; i++) {
parr[arr[i]-nMin]++;//统计各个数出现的次数
}
//输出结果
for (int i = 0; i < nSize; i++) {
for (int j = 0; j < parr[i]; j++)
{
printf("%d ", i + nMin);
}
}
printf("\n");
free(parr);
parr = NULL;
}
优化后:
1.遍历找到最大值最小值确定区间
int nMax=arr[0];//最大值
int nMin=arr[0];//最小值
//遍历数组得到数组的最大值和最小值
for (int i = 1; i < len; i++) {
if (arr[i] > nMax) nMax = arr[i];
if (arr[i] < nMin)nMin = arr[i];
}
2.申请计数器数组初值为0
//根据最大值最小值确定范围,申请数组
int nSize = nMax - nMin + 1;
int* parr = (int*)malloc(sizeof(int) * nSize);
memset(parr, 0, sizeof(int) * nSize);//初始化为0
3.对数字进行计数
for (int i = 0; i < len; i++) {
parr[arr[i]-nMin]++;//统计各个数出现的次数
}
4.获得各个分数最后出现的名次
// 得到名次
for (int i = 1; i < nSize; i++) {
parr[i] += parr[i-1];
}
5.申请一个长度与原数组相同的数组用来保存排序结果
//创建一个新数组,长度与原数组相同
int* pTemp = (int*)malloc(sizeof(int) * len);
memset(pTemp, 0, sizeof(int) * len);//初始化为0
6.进行排序
parr[arr[i] - nMin]获得arr[i]分数的排名,因为数组是从0开始需要-1
最后pTemp[ parr[arr[i] - nMin] - 1 ] = arr[i];就是把原数组对应元素放在新数组的对应最后出现的名次位置上
//进行排序
for (int i = len - 1; i >= 0; i--) {
//parr[arr[i] - nMin]获得arr[i]分数的排名,因为数组是从0开始需要-1
//最后pTemp[ parr[arr[i] - nMin] - 1 ] = arr[i];就是把原数组对应元素放在新数组的对应名次位置上
pTemp[ parr[arr[i] - nMin] - 1 ] = arr[i];//将原数组元素放到其对应名次上
parr[arr[i] - nMin]--;//因为已经在对应名次上插入了需要更新一下,对应元素最后出现的名次-1
}
7.把新数组的内容拷贝到原数组
for (int i = 0; i < len; i++) {
arr[i] = pTemp[i];
}
最终程序如下:
void CountSort2(int* arr, int len) {
int nMax = arr[0];//最大值
int nMin = arr[0];//最小值
//遍历数组得到数组的最大值和最小值
for (int i = 1; i < len; i++) {
if (arr[i] > nMax) nMax = arr[i];
if (arr[i] < nMin)nMin = arr[i];
}
//根据最大值最小值确定范围,申请数组
int nSize = nMax - nMin + 1;
int* parr = (int*)malloc(sizeof(int) * nSize);
memset(parr, 0, sizeof(int) * nSize);//初始化为0
for (int i = 0; i < len; i++) {
parr[arr[i] - nMin]++;//统计各个数出现的次数
}
// 得到各个分数最后出现的名次
for (int i = 1; i < nSize; i++) {
parr[i] += parr[i-1];
}
//创建一个新数组,长度与原数组相同
int* pTemp = (int*)malloc(sizeof(int) * len);
memset(pTemp, 0, sizeof(int) * len);//初始化为0
//进行排序
for (int i = len - 1; i >= 0; i--) {
//parr[arr[i] - nMin]获得arr[i]分数的排名,因为数组是从0开始需要-1
//最后pTemp[ parr[arr[i] - nMin] - 1 ] = arr[i];就是把原数组对应元素放在新数组的对应名次位置上
pTemp[ parr[arr[i] - nMin] - 1 ] = arr[i];//将原数组元素放到其对应名次上
parr[arr[i] - nMin]--;//因为已经在对应名次上插入了需要更新一下,对应元素最后出现的名次-1
}
//把新数组的内容拷贝到原数组
for (int i = 0; i < len; i++) {
arr[i] = pTemp[i];
}
free(pTemp);
pTemp = NULL;
free(parr);
parr = NULL;
}