非比较排序—计数排序

思路
空间换时间 非比较排序

  1. 先统计,再遍历输出
  2. 求出待排序数组最大值与最小值的差值,加1作为统计数组的长度
  3. 遍历原数组,进行统计,例:原数组值为2,将countArr位置的value加1(初始value=0)
  4. 遍历统计数组,按照下标值输出,例:index:5 value:3 ,输出三次5

按照上述方法进行的计数排序,是不稳定的排序,优化思路:
求出统计数组下标值在排序后数组具备稳定性的位置
比如1,2,1,第三个1在排序后数组的位置是在第二的位置,我们在排序中不能改变第一个1和第三个1的位置
具体方法: 统计数组从第二个元素开始,每一个元素都加上前面所有元素之和

这句话有点难理解
例:1 2 1 三个数,统计数组:0 2 1, 2 是第2个数,在最终排序中应该排名位置是第3,所以统计数组将前面三个value相加,0+2+1 = 3, 统计数组变成0 2 3,同理统计数组其它value也是从开始value到当前value之和,这个和代表当前统计数组下标在排序后数组中的排名
在逆序遍历时,每输出一个元素,统计数组对应value–(好难描述)

具体实现思路:

  1. 统计数组A中每个值A[i]出现的次数,存入C[A[i]]
  2. 从前向后,使数组C中的每个值等于其与前一项相加,这样数组C[A[i]]就变成了代表数组A中小于等于A[i]的元素个数
  3. 反向填充输出数组B:将数组元素A[i]放在数组B的第C[A[i]]个位置(下标为C[A[i]] – 1),每放一个元素就将C[A[i]]递减

代码:

public class CountSort {
    public static int[] countSort(int[] arr) {
        int max = arr[0];
        int min = arr[0];
        //求原数组max,min
        for(int i = 1; i < arr.length; i++) {
            if(arr[i] > max) {
                max = arr[i];
            }
            if(arr[i] < min) {
                min = arr[i];
            }
        }

        int d = max - min;
        //创建统计数组
        int[] countArr = new int[d+1];

        for (int i = 0; i < arr.length; i++) {
            //统计原数组值的个数
            countArr[arr[i] - min]++;
        }

        int sum = 0;
        for(int i = 0; i < countArr.length; i++) {
            //求出逆序遍历时元素在统计数组的排名(index+1)
            sum += countArr[i];
            countArr[i] = sum;
        }

        int[] sortArr = new int[arr.length];
        //逆序遍历
        for(int i = arr.length -1; i >= 0; i--) {
            //将原数组value放入输出数组指定位置
            sortArr[countArr[arr[i]- min] - 1] = arr[i];
            countArr[arr[i] - min]--;
        }
        return sortArr;
    }

    public static void main(String[] args) {
        int[] arr = new int[] {95, 94, 91, 98, 99, 90, 99, 93, 92, 91};
        int[] sortArr = countSort(arr);
        System.out.println(Arrays.toString(sortArr));
    }
}

计数排序缺点:

  1. 当数列最大最小值差距过大时,并不适用计数排序,浪费空间
  2. 当数列元素不是整数,并不适用计数排序
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值