计数排序及其优化

一、什么是计数排序

        计数排序是利用下标进行排序的算法,不用对要排序的数字进行比较,我们使用下面的例子进行说明。
        假设有20个随机整数,其取值范围在0~10之间,对其进行排序,由于这20个随机整数的取值范围是固定的,那么我们可以定义一个长度为11的数组,数组下标为从0到10,并且元素初始值全为0,然后遍历要排序的20个随机整数,将遍历到的数值对应的数组下标进行+1,直到遍历结束。如下图所示:
        假设我们要遍历的20个随机数为:9,3,5,4,8,9,1,2,7,8,5,3,6,7,9,0,4,7,2,4。创建一个长度为11的数组如下所示:
在这里插入图片描述
        然后我们开始遍历,遍历的第一个数字是9,则给新建立的数组下标为9的值+1,即:
在这里插入图片描述
        接着我们依此类推,直到遍历完要排序的数,遍历完之后的结果是:
在这里插入图片描述
        根据上面的数组的结果,我们就可以得到一个有序的数列,即:0,1,2,2,3,3,4,4,4,5,5,6,7,7,7,8,8,9,9,9。

二、计数排序的实现

public static int[] countSort(int[] array){
        //得到数列的最大值
        int max=array[0];
        for (int i=0;i<array.length;i++){
            if(array[i]>max){
                max=array[i];
            }
        }
        //根据数列最大值确定统计数组的长度
        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:
        对于上面的计数排序,我们不难发现存在这样一个问题:如果要排序的20个随机整数的范围在81~93之间,那么我们就需要建立一个长度为94的数组,这样就会造成新建的数组的前面81个空间位置就白白浪费了。
解决方法:
        我们可以通过使用使用数列的最大值-最小值+1作为统计数组的长度即可,同时使用最小值作为一个偏移量,用于计算整数在统计数组中的下标。
问题2:
        以上的计数排序只是按照输入数列从小到大的一个顺序对其进行输出而已,并没有对原始数列进行排序。如果遇到类似于对学生分数进行排序这样的现实问题,比如对于相同分数的学生就会造成分不清分数对应的是谁这样的问题。
解决方法:
        假如现在有5个学生的分数为:(学生A:90,学生B:99,学生C:95,学生D:94,学生E:95),使用上面的方法得到的统计数组如下所示:
在这里插入图片描述
        我们首先对统计数组进行变形,即从统计数组的第2个元素开始,每个元素都加上前面的所有元素之和,得到的新的统计数组如下所示:
在这里插入图片描述
        然后,我们从后向前依次遍历5位学生的分数,第1个为学生E95分,找到统计数组下标为5的元素,值是4,代表学生E成绩排名在第4位,然后对数组下标为5的元素的值-1,表示下次再遇到成绩为95分的,其位置就会在第3位,按照此方法就会得出最终的成绩排名顺序为:(学生A:90,学生B:94,学生C:95,学生D:95,学生E:99)。
优化后的计数排序的实现:

public static int[] countSortUpdated(int[] array){
        //得到数列的最大值和最小值,并算出差值d
        int max=array[0];
        int min=array[0];
        for (int i=0;i<array.length;i++){
            if (array[i]>max){
                max=array[i];
            }
            if (array[i]<min){
                min=array[i];
            }
        }
        int d=max-min;
        //创建统计数组并统计对应元素的个数
        int[] countArray=new int[d+1];
        for (int i=0;i<array.length;i++){
            countArray[array[i]-min]++;
        }
        //统计数组做变形,后面的元素等于前面的元素之和
        for (int i=1;i<countArray.length;i++){
            countArray[i]+=countArray[i-1];
        }
        //倒序遍历原始数列,从统计数组中找出正确的位置,输出到结果数组
        int[] sortedArray=new int[array.length];
        for (int i=array.length-1;i>=0;i--){
            sortedArray[countArray[array[i]-min]-1]=array[i];
            countArray[array[i]-min]--;
        }

        return sortedArray;
    }

注:以上内容均为《漫画算法》所学。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
计数排序(Counting Sort)是一种非比较型整数排序算法,它对输入的数据进行计数,然后根据计数值直接输出排序结果。计数排序适用于数据规模较小且数据分布均匀的情况,它的时间复杂度为O(n+k),其中n是输入数据的数量,k是输入数据的最大值。 在Python中实现计数排序的代码示例如下: ```python def counting_sort(arr): # 确定最大值和计数数组的长度 max_val = max(arr) count_len = max_val + 1 # 初始化计数数组 count = * count_len # 统计每个元素出现的次数 for num in arr: count[num] += 1 # 计算每个元素应该放置的位置 for i in range(1, count_len): count[i] += count[i-1] # 创建输出数组并排序 output = * len(arr) for num in arr: output[count[num]-1] = num count[num] -= 1 return output ``` 上述代码中,我们首先确定输入数组中的最大值,并根据最大值创建一个计数数组,长度为最大值加一。然后统计输入数组中每个元素出现的次数,并将计数结果存入计数数组。接下来,我们通过累加计数数组中的元素,计算每个元素应该放置的位置。最后,我们根据计数数组中的计数值和位置信息,将输入数组中的元素排序并输出。 使用计数排序算法对整数数组进行排序的时间复杂度为O(n+k),空间复杂度为O(n)。在Python中实现计数排序算法时,需要占用一定的额外空间来存储计数数组和输出数组。但是,计数排序算法的稳定性较好,适用于整数数组的排序。在实际应用中,需要根据具体的数据规模和分布情况选择合适的排序算法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值