【OI之路】04排序搜索-3计数排序

版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎前往zory.cf获得最佳体验 https://blog.csdn.net/Zory_Programmer/article/details/78146996

建议前往我的网站获得最佳体验。

4.4 计数排序

1)操作

假设将要被排序的数组是A,排序后存储到B数组,C为临时数组。所谓计数,是指通过C[i]数组计算大小=i的元素个数(这就是为什么它需要一个元素最大值m)。在此基础上,r的定义改为计算“元素≤i”的元素个数,从前往后递推。
下一步,逆序循环,从n(数组元素个数)到1,将A[i]放到B中第C[A[i]]个位置上,并减小C[A[i]]。

2)原理

1.C[A[i]]表示≤A[i]的元素个数,正好是A[i]排序后应该在的位置。而且从n到1逆序循环,可以保证相同元素间的相对顺序不变,这也是计数排序稳定性的体现。在数组A有附件属性的时候(即使用结构体),稳定性是非常重要的。(如果从1到n,则相同元素的相对顺序会逆序,但结果也是正确的)
2.前提及适用范围: 元素个数多而且都是非负整数,最大值不大
原因:A中的元素不能大于m,而且元素要作为数组的下标,所以元素应该为非负整数。而且如果A中有很大的元素,不能够分配足够大的空间。
3. 时间复杂度分析:O(n)。属于非比较类型的排序,比较类型的排序的时间下界都是O(nlogn)。

3)代码

void csort(int A[],int B[],int n,int m)
{
    int C[m+1]={0};
    for(int i=1;i<=n;i++) C[A[i]]++;
    for(int i=1;i<=m;i++) C[i]+=C[i-1];
    for(int i=n;i>=1;i--) B[C[A[i]]--]=A[i];
}

4)扩展。

对负数排序的扩展思路:计数排序要求元素能够作为数组的下标,自然不能是负数。我的思路是先把负数和非负数分离开来,对负数取绝对值,再对这两组数分别计数排序,最后再把两组数合并可以了。

猜你喜欢

转载自blog.csdn.net/Zory_Programmer/article/details/78146996