桶排序算法

133 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第14天,点击查看活动详情

本文系作者 不太自律的程序猿原创,转载请私信并在文章开头附带作者和原文地址链接。

桶排序算法

桶排序 (Bucket sort) 或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θn))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。

算法思路

1.根据待排序集合中的数据,确定映射规则和桶数量;

2.遍历待排序集合,将每一个元素根据映射规则,移动到对应的桶中;

3.对每一个桶中元素进行排序;

4.一次输出每个桶中的数据,得到整个有序的集合;

示例:

对于一个数组: {21,8,6,11,36,50,27,42,0,12}

步骤:

1.找出待排序数组中的最大值max,最小值min

最大值max = 50, 最小值min = 0

2.桶的数量为(max-min)/arr.length+1

桶的数量=(50-0)/10+1 = 6

3.遍历数组arr,计算每个元素arr[i]放的桶

存放桶的下标=(arr[i]-min)/arr.length

桶排序1.png

4.每个桶各自排序

桶排序2.png 桶内排序可以选择比较排序或者其他排序。

5.遍历桶数组,把排序好的元素放进输出数组

{0,6,8,11,12,21,27,36,42,50}

我们可以使用数组或者ArrayList存储桶,在桶内使用ArrayList存储桶里面的数据。

代码实现

    public static void bucketSort(int[] arr){
        //max
        int max = arr[0];
        for (int i =1; i <arr.length-1;i++){
            if (arr[i]>max){
                max = arr[i];
            }
        }
        //min
        int min = arr[0];
        for (int i =1; i <arr.length-1;i++){
            if (arr[i]<min){
                min = arr[i];
            }
        }
        //确定桶的数量
        ArrayList<ArrayList<Integer>> buckets = new ArrayList<>();
        int bucketNumber = (max - min)/arr.length + 1;
        for (int i = 0; i<bucketNumber;i++){
            buckets.add(new ArrayList<>());
        }
        //遍历arr,把对应数据放在桶里面
        for (int i = 0 ;i<arr.length-1;i++){
            buckets.get((arr[i]-min)/arr.length).add(arr[i]);
        }
        //对每个桶分别排序
        for (int i = 0 ;i<buckets.size();i++){
            Collections.sort(buckets.get(i));
        }
        //遍历每个桶里面的每个数据,输出到arr
        int k = 0;
        for (int i = 0 ;i<buckets.size();i++){
            ArrayList<Integer> list = buckets.get(i);
            for (int j=0;j<list.size();j++){
                arr[k++] = list.get(j);
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = {21,8,6,11,36,50,21,47,0,12};
        System.out.println("排序前:"+Arrays.toString(arr));
        bucketSort(arr);
        System.out.println("排序后:"+Arrays.toString(arr));
    }

image.png

算法性能分析

时间复杂度

如果要排序的数据有n个,我们把它们分在m个桶中,这样每个桶里的数据平均为k=n/mk = n/m。如果每个桶内使用快速排序,每个桶内排序的时间复杂度就为O(klog2k)O(k*log2 ^ k)。m个桶就是mO(klog2k)=mO((n/m)log(n/m))=O(nlog(n/m))m*O(k*log2 ^ k)= m*O((n/m)*log(n/m))=O(nlog(n/m))。当桶的个数m接近数据个数n时,log(n/m)log(n/m)就是一个较小的常数,所以时间复杂度接近O(n)O(n)

桶排序的最好情况时间复杂度为O(n)O(n),如果数据分配到桶的分布情况极度倾斜,比如所有数据都分配到了一个桶,那么这时的时间复杂度就是最坏的情况,至于用O表示为多少,就需要看桶排序结合的排序算法的时间复杂度是什么了,如果是快速排序,那么就是O(nlogn)O(nlogn),插入排序则是On2O(n^2)

空间复杂度

额外空间复杂度:O(N+M)O(N + M) 感谢诸君的观看,文中如有纰漏,欢迎在评论区来交流。如果这篇文章帮助到了你,欢迎点赞👍关注。