算法之计数排序

原理:用一个数组记录待排序数组中出现的数字。
最低位代表最小值,偏移量是记录数组中的下标;
待排序数组: 2 1 4 可以表示为
记录数组: 1 1 0 1 数组长度为(4-1+1)

然后根据记录数组输出结果

 public static void countSort(int [] arr){
        if(arr==null){
            return;
        }
        if(arr.length<=1){
            return;
        }
        int maxValue=getMax(arr);
        int minValue=getMin(arr);

//        创建一个数组来记录出现的数字
        int[] recordArr=new int[maxValue-minValue+1];

//        看一下哪个数字出现了
        for(int i=0;i<arr.length;i++){
            int curNum=arr[i];
//            记录出现的数字以及他出现的次数
            recordArr[curNum-minValue]+=1;
        }

//        输出出现在待排序数组中出现的数字
        int curArrIndex=0;
        int len=arr.length;
        int curRecordIndex=0;


      while (curArrIndex<len){
          if(recordArr[curRecordIndex]>0){
//             该数字在待排序数组中出现
              arr[curArrIndex]=minValue+curArrIndex;
              recordArr[curArrIndex]--;
              curArrIndex++;

          }else {
//              该书在在待排序数组中没有出现
              curRecordIndex++;
          }


      }

    }

//    获取数组中的最大值
    public static int getMax(int [] arr){
        int res=Integer.MIN_VALUE;
        for(int i=0;i<arr.length;i++){
            if(res<arr[i]){
                res=arr[i];
            }
        }
        return res;
    }
//    获取数组中的最小只
    public static int getMin(int []arr){
        int res=Integer.MAX_VALUE;
        for(int i=0;i<arr.length;i++){
            if(res>arr[i]){
                res=arr[i];
            }
        }
        return res;
    }

但上面这种方法,本质上并未对待排序数组进行排序(操作),如果排序的是对象的话,就无法使用,而且也不能解决稳定性问题

解决方法:
在获得记录数组后,更新记录数组,每一位+=前一位,这样一来,记录数组的值-1代表 所记录数字在排序结果中的下标

待排序数组:1 4 2
记录数组:1 1 0 1
更新后: 1 2 2 3

从后面读起:
待排序数组中,2对应位置为下标2-1;4对应下标为3-1;1对应下表为1-1

//进化版计数排序
//    由于初级版本通过记录出现的数字,然后直接输出获得数组,并没有实际操作待排序数组
//    这种排序只能对对象进行排序,并且是不稳定的

    public static void countSort(int[] arr){
        if(arr==null||arr.length<=1){
            return;
        }


        int maxValue=getMax(arr);
        int minValue=getMin(arr);

//        创建一个数组来记录出现的数字
        int[] recordArr=new int[maxValue-minValue+1];

//        看一下哪个数字出现了
        for(int i=0;i<arr.length;i++){
            int curNum=arr[i];
//            记录出现的数字以及他出现的次数
            recordArr[curNum-minValue]+=1;
        }
        
//        更新记录数组
        for(int i=1;i<recordArr.length;i++){
            recordArr[i]+=recordArr[i-1];
        }
        
        int []res=new int[arr.length];
        
        for(int i=arr.length-1;i>=0;i--){
            int curValue=arr[i];
//            获得当前数字的 排序后下标
            int index=recordArr[curValue-minValue]-1;
            recordArr[curValue-minValue]--;
            res[index]=curValue;
        }
        arr=res;
    }

    //    获取数组中的最大值
    public static int getMax(int [] arr){
        int res=Integer.MIN_VALUE;
        for(int i=0;i<arr.length;i++){
            if(res<arr[i]){
                res=arr[i];
            }
        }
        return res;
    }
    //    获取数组中的最小只
    public static int getMin(int []arr){
        int res=Integer.MAX_VALUE;
        for(int i=0;i<arr.length;i++){
            if(res>arr[i]){
                res=arr[i];
            }
        }
        return res;
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值