排序之桶排序

桶排序

桶排序可以看成是计数排序的升级版,它将要排的数据分到多个有序的桶里,每个桶里的数据再单独排序,再把每个桶的数据依次取出,即可完成排序。这些桶的size根据被排序的数字的差值决定,只需要根据这些桶的size依次把这些被排序的数字放入即可,再将桶中的数字排序输出即可。

在这里插入图片描述
我们拿一组计数排序啃不掉的数据 [ 500,6123,1700,10,9999 ] 来举例。

第一步,我们创建 10 个桶,分别来装 0-1000 、1000-2000 、 2000-3000 、 3000-4000 、 4000-5000 、5000-6000、 6000-7000 、7000-8000 、8000-9000 区间的数据。
在这里插入图片描述
第二步,遍历原数组,对号入桶。
在这里插入图片描述
第三步,对桶中的数据进行单独排序,只有第一个桶中的数量大于 1 ,显然只需要排第一个桶。在这里插入图片描述
最后,依次将桶中的数据取出,排序完成。
在这里插入图片描述
但是如果数据经过桶的划分之后,桶与桶的数据分布极不均匀,有些数据非常多,有些数据非常少,比如[ 8,2,9,10,1,23,53,22,12,9000 ]这十个数据,我们分成十个桶装,结果发现第一个桶装了 9 个数据,这是非常影响效率的情况,会使时间复杂度下降到 O(nlogn),解决办法是我们每次桶内排序时判断一下数据量,如果桶里的数据量过大,那么应该在桶里面回调自身再进行一次桶排序

public static void sort(int[] arr){
    //最大最小值
    int max = arr[0];
    int min = arr[0];
    int length = arr.length;

    for(int i=1; i<length; i++) {
        if(arr[i] > max) {
            max = arr[i];
        } else if(arr[i] < min) {
            min = arr[i];
        }
    }

    //最大值和最小值的差
    int diff = max - min;

    //桶列表
    ArrayList<ArrayList<Integer>> bucketList = new ArrayList<>();
    for(int i = 0; i < length; i++){
        bucketList.add(new ArrayList<>());
    }

    //每个桶的存数区间
    float section = (float) diff / (float) (length - 1);

    //数据入桶
    for(int i = 0; i < length; i++){
        //当前数除以区间得出存放桶的位置 减1后得出桶的下标
        int num = (int) (arr[i] / section) - 1;
        if(num < 0){
            num = 0;
        }
        bucketList.get(num).add(arr[i]);
    }

    //桶内排序
    for(int i = 0; i < bucketList.size(); i++){
        //jdk的排序速度当然信得过
        Collections.sort(bucketList.get(i));
    }

    //写入原数组
    int index = 0;
    for(ArrayList<Integer> arrayList : bucketList){
        for(int value : arrayList){
            arr[index] = value;
            index++;
        }
    }
}
发布了12 篇原创文章 · 获赞 6 · 访问量 1296

猜你喜欢

转载自blog.csdn.net/NINIYUANJ123/article/details/103509360