1. 算法的步骤如下:
- (1)找出待排序的数组中最大和最小的元素
- (2)统计数组中每个值为i的元素出现的次数,存入数组C的第i项
- (3)对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)
- (4)反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1
简单点说,就是把待排序数组(这里用arr表示)arr的最大值max和最小值min找出来,然后以此创建一个临时数组temp_arr,这临时数组的长度就是max-min+1,然后这个临时数组temp_arr的下标
min-min --> max-min (为什么要这样,因为数组下标是从0开始的,后面用到再+min不就解决了)
,而临时数组这些下标 index 对应的值就是arr中index出现的次数,后面重新填回arr数组就行了
(不理解的建议多去看视频,b站搜,视频秒懂,文章晦涩难懂)
2. 动图演示
//找出待排序数组的最大值和最小值
void arr_max_min(int a[], int len,int& min, int& max)
{
if (len < 2)return;
min = a[0];
max = a[0];
for (int i = 1; i < len; i++)
{
if (a[i] < min)
{
min = a[i];
}
if (a[i] > max)
{
max = a[i];
}
}
}
//计数排序函数
void count_sort(int a[], int len)
{
if (len < 2)return;
int min, max;
// 获取待排序数组元素中的最小和最大值。
arr_max_min(a, len, min, max);
// 分配并初始化临时数组。
int temparr_len = max - min + 1; //临时数组的长度
int* temp_arr = new int[temparr_len]; //new一个临时数组
memset(temp_arr, 0, sizeof(int)* temparr_len); //初始化为0
// 临时数组计数。
for (int i = 0; i < len; i++)
{
temp_arr[ a[i] - min ]++;
//只要把计数排序原理弄懂,就知道这里为什么这样写了
//(因为临时数组下标从0开始,待排序数组最小值-min 就是 0,待排序数组最大值-min就是临时数组的末尾)
}
// 把临时数组计数的内容恢复到到a数组中。
int index = 0;
for (int i = 0; i < temparr_len; i++)
{
for (int j = 0; j < temp_arr[i]; j++)
{
a[index++] = i + min;
}
}
delete[] temp_arr; // 释放临时数组。
}