概念及其介绍:
通过统计序列中各个元素出现的次数,完成对整个序列的升序或降序排序。
算法思想:
- 先遍历整个数组(arr[N]),然后找到整个数组中最大的那个元素max,然后创建一个max+1大小的数组(讲解为input[max])和一个与原数组大小一样的数组(讲解为output[N])(最后会进行拷贝)
- 以数组arr中的元素作为数组input中的下标,统计arr中元素出现的次数,然后以该元素为下标将元素出现的次数存储在数组input中
- 进一步加工数组input中的元素,按照公式input[ i ] = input[ i ] + input[ i -1] ,修改数组input中的数据
- 数组arr中的元素为下标对应在input数组中的元素的值,其值减1作为数组output的下标,将数组arr此时对应的值存放在改下标对用的数组output中(这里可能有点绕,但是多看几遍就应该能理解)
- 最后一步,即将数组output中的元素值对应拷贝到数组arr中。在答应出来即可。
算法过程演示:
1) 找到序列中的最大值(用 max 表示)。对于 {4, 2, 2, 8, 3, 3, 1} 序列来说,最大值是 8。
2) 创建一个长度为 max+1、元素初值全部为 0 的数组(Python 中可以使用列表),为数组中 [1,max] 区域内的各个空间建立索引:
找到序列中的最小值(用 min 表示),作为数组下标为 1 的存储空间的索引;
待排序的元素都是整数,可以直接将数组下标作为各个存储空间的索引,如下图所示。
3)统计待排序序列中各个元素的出现次数,存储到以该元素为索引的数组空间中。例如,待排序序列中元素 2 出现了两次,所以索引(下标)为 2 的数组空间中存储 2 。更新后的数组如下图所示:
4) 进一步加工数组中存储的数据。从数组下标为 1 的位置开始,按照公式修改数组中存储的元素
其中 i 的取值范围是 [1, max],修改后的数组为:
5) 遍历待排序列中的元素,以该元素为索引获取数组中存储的值,此值即为序列排序后元素应处的位置。
举个例子,序列中第一个元素是 4,数组中索引 4 对应的值为 6,因此序列排序后元素 4 位于第 6 的位置处,如下图所示:
代码示例:
#define SE 9
//查找出数组最大值
int getmax(int arr[],int n)
{
int i = 0;
int max = arr[0];
for (i = 0; i < n; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
return max;
}
//计数排序
void the_counting_sort(int arr[])
{
//首先找到数组中的最大值
int max = getmax(arr, SE);
//然后创建一个max+1长度的数组和一个输出拷贝数组
int input[MAX] = { 0 };
int output[SE] = { 0 };
//统计待排序序列中各个元素的出现次数,存储到以该元素为索引的数组空间中
for (int i = 0; i < SE; i++)
{
//以待排序序列中的元素为下标存储数据,
//当arr数组中重复出现同一个元素的时候,以该元素为下标的input数组中的相应的元素加1
input[arr[i]]+= 1;
}
//进一步加工数组中存储的数据.利用公式进行修改数组input中的元素值
for (int i = 1; i <= SE; i++)
{
input[i] = input[i] + input[i - 1];
}
//遍历待排序列中的元素,以该元素为索引获取数组input中存储的值,此值即为序列排序后元素应处的位置
for (int i = 0; i < SE; i++)
{
output[input[arr[i]] - 1] = arr[i];
//当确定了一个元素排序后的位置,需要将数组中该元素为索引对应的值减去 1
input[arr[i]]--;
}
//进行拷贝,将数组output中的元素值拷贝到数组arr中,然后再打印arr即可
for (int i = 0; i < SE; i++)
{
arr[i] = output[i];
}
}