计数排序和稳定的计数排序

计数排序不是基于元素比较,而是利用数组下标来确定元素的正确位置。计数排序是一个稳定的排序算法。当输入的元素是 n 个 0到 k 之间的整数时,时间复杂度是O(n+k),空间复杂度也是O(n+k),其排序速度快于任何比较排序算法。当k不是很大并且序列比较集中时,计数排序是一个很有效的排序算法。
算法思路
计数排序的算法思路是定义一个大小为序列最大值-最小值的大小的数组,遍历每一个元素,将其映射到数组中,例如最大值和最小值相差10,就定义一个大小为10的数组,每一个整数按照其值对号入座,对应数组下标的元素进行加1操作。

比如第一个整数是9,那么数组下标为9的元素加1:
在这里插入图片描述
最终,数列遍历完毕时,数组中的每一个值,代表了数列中对应整数的出现次数。有了这个统计结果,排序就很简单了,直接遍历数组,输出数组元素的下标值,元素的值是几,就输出几次。
不稳定的计数排序
算法的实现可以分为三个步骤

  1. 第一步 定义最大值和最小值,和一个最后添加会原来数组的下标index,然后遍历输入的序列,找到最大值和最小值赋值给max和min。
 public int[] countingSort(int[] array){
        int index = 0;
        int min = array[1];
        int max = array[1];
        for (int i:array) {
            if (i>max){
                max = i;
            }
            if (i<min){
                min = i;
            }
        }
  1. 第二步 定义一个大小为max-min+1大小的数组,遍历序列将序列中的每一个元素减去min,将其映射到数组下标中,如果有相同的元素,则++;
        int[] list = new int[max-min+1];
        for (int i:array){
            list[i-min]++;
        }
  1. 第三步 遍历临时储存的list数组,当list[i]的大小不等于0,即还有元素,将其赋给原数组array,注意这里的赋值是i+min而不是list[i+min]
        for (int i = 0; i < list.length; i++) {
            while (list[i]>0){
                array[index++] = i+min;
                list[i]--;
            }
        }
        return array;
    }

稳定的计数排序
稳定的基数排序跟上者的差别是在,如果值相同,则遵循原表固有顺序。
算法思路
算法的具体思路是在遍历完序列映射到数组中后,例如下图是已经映射好的数组。原序列为{90,99,95,95,94}
在这里插入图片描述在第二个下标开始,加上前面元素的和,例如上图第一个下标为1,那么第二个下标的数值就为本身的0加上前面的1等于1。第三个就等于第三加上前面的数的总个数,以此类推。
这个数值其实就代表了映射的元素在原数组中因该在的位置,整个数组中有用的下标就只有0,4,5,9四个下标是由代表有数值的,其他都是空的,下标为0的数值为1即使第一个数字,下标为4的数值为2即第二个数,下标为5的数值为4,我们看到95是有两个数,所以是第3的数和第4的数,最后一个为第五的数。
理解了上面后,在赋值给原数组的过程中,从后往前遍历,例如原序列为{90,99,94,95,95},第一个数为95,在映射的数组中下标为4,即原数组array[4]=95,然后4-1=3,即如果有第二个95,它的位置就是3,然后第二个数是95,这时候下标为3,即array[3]=95,依照这种算法随后得到的结果就为{90,94,95,95,99},而且是稳定的排序。

在这里插入图片描述代码的实现分为两步
第一步在得到了映射后的数组countArray后,从第二个下标开始,加上前面的数的个数,即countArray[i] = countArray[i-1]+countArray[i]。

        for (int i = 1; i < countArray.length; i++) {
            countArray[i] = countArray[i-1]+countArray[i];
        }

第二步是定义一个数组用于存储,countArray[i-min]即映射数组的值,即第几个元素,例如第5个元素,那么下标就为4,所以要-1,然后countArray[i-min]自减。

        int[] sortArray = new int[array.length];
        for (int i:array){
            sortArray[countArray[i-min]-1] = i;
            countArray[i-min]--;
        }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值