排序算法 - 计数排序

概念:


计数排序不是一个比较排序算法,该算法于1954年由 Harold H. Seward提出,通过计数将时间复杂度降到了O(N),利用数组下标来缺的元素的正确位置


案例:


假设数组中有10个随机数,取值范围0~10,要求用最快的速度把这20个证书从小到大进行排序

考虑到这些整数只能够在 0、1、2、3、4、5、6、7、8、9、10 这11个数中取值,取值范围有限。所以,可以根据这有限的范围,建立一个长度为11的数组,数组下标从0-10,元素初始值全为0

在这里插入图片描述

假设10个随机数整数值如下

9,3,5,4,9,1,2,7,8,1

第一次计数

在这里插入图片描述

第二次计数

在这里插入图片描述
第三次计数

在这里插入图片描述
第四次计数

在这里插入图片描述
第五次计数

在这里插入图片描述

第六次计数

在这里插入图片描述
第七次计数

在这里插入图片描述
第八次计数

在这里插入图片描述

第九次计数

在这里插入图片描述
第十次计数

在这里插入图片描述

最终,当数列遍历完毕时,数组状态如下

在这里插入图片描述
该数组中每一个下标位置的值代表数列中对应整数出现的次数。

有了这个统计结果,排序就简单多了,直接便利数组,输出数组元素的下标值,元素的值时几,就输出几次

1,1,2,3,4,5,7,8,9,9

显然,现在输出的数列已经是有序的了。

这就是计数排序的基本过程,它适用于一定范围内的整数排序。在取值范围不是很大的情况下,它的性能甚至快过那些时间复杂度为 O(nlogn) 的排序。


# 代码实现:
public class test {

    public static void main(String[] args) {
        int[] array = new int[] {4,4,6,5,3,2,8,1,7,10};
        int[] sortedArray = countSort(array);
        System.out.println(Arrays.toString(sortedArray));
    }

    public static int[] countSort(int[] array){
        //1. 得到数列最大值
        int max = array[0];
        for (int i = 1; i < array.length; i++) {
            if(array[i] > max){
                max = array[i];
            }
        }
        //2. 根据数列最大值确定统计数组的长度
        int[] countArray = new int[max+1];
        for(int i=0; i<array.length; i++){
            countArray[array[i]]++;
        }
        //遍历统计数组,输出结果
        int index = 0;
        int[] sortedArray = new int[array.length];
        for(int i=0; i<countArray.length; i++){
            for(int j=0; j<countArray[i]; j++){
                sortedArray[index++] = i;
            }
        }
        return sortedArray;
    }

}

[1, 2, 3, 4, 4, 5, 6, 7, 8, 10]

这段代码在开头有一个步骤,就是求数列的最大整数值max。后面创建 的统计数组countArray,长度是max+1,以此来保证数组的最后一个下 标是max。


计数排序优缺点


  1. 当数列最大和最小值差距过大时,并不适合用计数排序

例如给出20个随机整数,范围在0到1亿之间,这时如果使用计数排序,需要创建长度为1亿的数组,不但浪费空间,而且时间复杂度也会随之升高

  1. 当数列元素不是整数时,也不适合用计数排序

如果数列中的元素都是小数,如25.213,或0.00 000 001 这样的数字,则无法创建对应统计数组,这样显然无法进行计数排序。

对于这些局限性,另一种线性时间排序算法做出弥补、这周排序算法叫做桶排序




个人博客地址:http://blog.yanxiaolong.cn 『纵有疾风起,人生不言弃』

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值