vlambda博客
学习文章列表

十大经典排序(九)--桶排序

桶排序思想:

       桶排序用一句话来说就是 划分多个范围相同的区间,将待排序元素分配到各个区间中,每个子区间进行自排序,最后合并各个自区间数据

       它和计数排序十分类似,可以说是计数排序的一个升级版,不了解计数排序的可以看下这篇 

       在计数排序中我们知道,当待排序的元素最大值和最小值相差很大时,计数排序空间浪费巨大,而桶排序则能解决这个问题

         

桶排序的”桶“是什么概念?

        桶代表的其实是一个区间范围,里面可以承载一个或多个元素,就像一个容器一样。桶排序的第一步就是创建桶,确定区间范围。


算法步骤:

  1. 创建桶(设置一个定量的数组当作空桶),确定桶的区间范围;

  2. 遍历输入数据,并且把数据一个一个放到对应的桶里去;

  3. 对每个不是空的桶进行排序(这里排序方法随意,可以使用桶排序进行套娃);

  4. 从不是空的桶里把排好序的数据拼接起


这里找一张图方便大家理解:

紧接着咱们看代码实现


代码:

 1private static void sort(int[] arr) {
2    if (arr == null || arr.length < 2) {
3        return;
4    }
5    //确定最大值最小值
6    int max = Integer.MIN_VALUE;
7    int min = Integer.MAX_VALUE;
8    for (int value : arr) {
9        max = Math.max(value, max);
10        min = Math.min(value, min);
11    }
12    //创建桶的个数  这个设置桶的个数和原数组一样大小
13    int size = arr.length;
14    ArrayList<ArrayList<Integer>> lists = new ArrayList<>(size);
15
16    //确定每只桶的范围 这里加1 防止最大值溢出
17    int avg = (max - min) / size + 1;
18    for (int i = 0; i < size; i++) {
19        lists.add(new ArrayList<>());
20    }
21    int d = max - min;
22    for (int value : arr) {
23        //确定该元素放入哪个桶
24        int index = (value - min) / avg;
25        lists.get(index).add(value);
26    }
27    //对每个桶进行排序  这里采用Java原生API
28    for (ArrayList<Integer> list : lists) {
29        Collections.sort(list);
30    }
31    //倒回原数组
32    int i = 0;
33    for (List<Integer> list : lists) {
34        for (Integer num : list) {
35            arr[i++] = num;
36        }
37    }
38}


由上述分析和代码可知,桶排序的的快慢取决于数据的分布:

  • 当输入的数据可以均匀的分配到每一个桶中,排序最快

  • 当输入的数据被分配到了同一个桶中,排序最慢

当桶越多时,每个桶内数据就会越少,那么排序就会越快,相应的空间损耗也就会越大,其实就是时间和空间的抉择


以上仅是个人思路解法,觉得还不错欢迎点赞关注分享


往期精彩推荐