【算法精解】计数排序

【算法精解】计数排序

  1. 基本认识:是一个特殊的桶排序。基于比较排序的排序方法,其复杂度无法突破nlogn 的下限,但是非比较排序却可以突破该下限,甚至达到O(n)的时间复杂度。当有n个数据时,所处的范围并不大,最大值是k,那么就划分k个桶。每个桶都存储相同的数据。这样可以省掉桶内排序的时间。
  2. 时间复杂度:因为整个过程只涉及到扫描遍历操作,所以时间复杂度是O(n+k)。【n为元素个数,k为待排序最大值与最小值之差】
  3. 优缺点:适用于待排序数据的范围不大的情况,若范围比较大,会产生很多空桶,造成空间浪费。
  4. 适用场景:以高考为例,假设某省有50万考生,高考成绩满分是750分,我们可以分配751个桶(最低0分,最高750分),遍历50万考生的成绩,划分到751个桶中,最后只需要依次扫描桶,就可以输出排序好的数据。
  5. 排序思路
对A[8]进行排序,其中A[8] = {0,2,3,5,2,3,0,3},min=0,max=5
1、遍历A[8],得到C[6]={2,0,2,3,0,1}。//C[0]=2的含义为:值为0的数据再A[]中有两个
2、对C[6]数组顺序求和,C[k]存储小于等于分数k的考生个数,C[6]={2,2,4,7,7,8}。//C[1]=2的含义为:A[]中 <= 1的值有两个
3、新建一个数据R[8]用于存储排序好的数据。
4、从后向前遍历数据A[8],A[8]的倒数第一个数为3,C[6]下标为3的数为7,表明数组A中小于等于3的有7个人,所以讲这个3放入R[8]的第7个位置,C[6]下标为3位置的数变为7-1=6。此时R[8]={0,0,0,0,0,0,3,0},C[6]={2,2,4,6,7,8}。
5、依次类推,扫描A[8]剩下的数据。最后R[8]就是排序好的数据。
  1. Java代码实现
public class Order {
    public static void main(String[] args) {
        int[] beforArr = {13, 19, 15, 11, 7, 11, 25, 21, 29, 17, 15, 14, 17, 29, 28, 22};
        System.out.println("待排序数据:" + Arrays.toString(beforArr));
        int[] afterArr = countingSort(beforArr);
        System.out.println("排序之后数据:" + Arrays.toString(afterArr));
    }

    public static int[] countingSort(int[] beforArr){
        int max = beforArr[0];//记录最大值
        int min = beforArr[0];//记录最小值

        for (int arr : beforArr) {
            //获取最大值
            if (arr > max){
                max = arr;
            }
            //获取最小值
            if (arr < min){
                min = arr;
            }
        }

        //记录容器的大小
        int size = max - min + 1;

        //定义桶容器
        int[] bucket = new int[size];

        //计算每个元素的个数,放入桶中
        for (int i=0; i<beforArr.length; i++){
            //最小值min对应数组索引0,依次类推
            bucket[beforArr[i]-min] ++;
        }

        //依次累加
        for (int i=1; i < size; i++){
            bucket[i] = bucket[i] + bucket[i-1];
        }

        //存放排序好数据的数组
        int[] afterArr = new int[beforArr.length];

        //倒序遍历待排序数据
        for (int i=beforArr.length-1; i>=0; i--){
            //获取对应桶下标存储的个数
            int index = bucket[beforArr[i]-min] - 1;
            //存入afterArr
            afterArr[index] = beforArr[i];
            //对应桶下标存储个数-1
            bucket[beforArr[i]-min] --;
        }

        return afterArr;
    }
}
发布了9 篇原创文章 · 获赞 10 · 访问量 1021

猜你喜欢

转载自blog.csdn.net/weixin_43954926/article/details/103742148