桶排序 | 详细思路、Java实现与注释

一、原理

桶排序顾名思义就是得有桶,在桶排序中,我们把未排序数据分成n组,这n组就对应放到n个桶里。那么要把数据放到桶里,有什么规则呢?

首先,我们保证这n个桶是有序的;其次,我们把未排序序列分到这些桶里,然后各个桶分别对数据进行排序;最后,我们按照桶的顺序,把里面的数据按序依次取出,得到一个有序序列,那就是我们最终的排序结果。

举个例子,如图,{21,14,2,3,19,23,6,27,3}是一个无序数组,现在我们要用对它进行桶排序。

首先把桶的范围划分清楚,分别是0-9,10-19,20-29;然后把数组中的数字放入对应范围的桶中;最后在每个桶里面我们都进行各自的排序。现在我们发现每个桶里面的数据都是各自有序的了,可以按照桶的顺序,即0-9,10-19,20-29这样的顺序把数据2,3,3,6,11…全部取出来,赋值回原数组,这就是我们的桶排序结果。

在这里插入图片描述

二、实现代码示例

package Sort;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class BucketSort {
    public static void main(String[] args) {
        int[] arr = {21,14,2,3,19,23,6,11,3};
        int[] res = bucketSort(arr);
        System.out.println(Arrays.toString(res));
    }

    public static int[] bucketSort(int[] arr){
        // 计算最大值与最小值,方便分桶
        int max = Integer.MIN_VALUE;          // max设置为最小值,方便比较
        int min = Integer.MAX_VALUE;          // min设置为最大值,方便比较
        // 遍历原数组所有元素,找出数组中的最大值和最小值
        for(int i = 0; i < arr.length; i++){
            max = Math.max(max, arr[i]);
            min = Math.min(min, arr[i]);
        }

        // 计算桶的数量:元素范围/元素数量 + 1
        int bucketNum = (max - min) / arr.length + 1;
        ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
        for(int i = 0; i < bucketNum; i++){
            bucketArr.add(new ArrayList<Integer>());
        }

        // 根据元素大小将元素分配到对应范围的桶中
        for(int i = 0; i < arr.length; i++){
            int num = (arr[i] - min) / (arr.length);      
            bucketArr.get(num).add(arr[i]);
        }

        // 对每个桶进行排序
        for(int i = 0; i < bucketArr.size(); i++){
            Collections.sort(bucketArr.get(i));
        }

        // 将桶中的元素赋值到原序列
        int index = 0;
        for(int i = 0; i < bucketArr.size(); i++){
            for(int j = 0; j < bucketArr.get(i).size(); j++){
                arr[index++] = bucketArr.get(i).get(j);
            }
        }
        return arr;
    }

}

三、算法分析

1.特点与应用场景

桶排序要求可以很容易地划分到不同桶中,并且所有桶都是有序排列的。

桶排序要求数据跨度范围不是很大,可以均匀分布到每个桶中。若每个桶内部使用快速排序,有的桶中数据非常多,有的桶里数据非常少,那么桶排序的时间复杂度将会退化为O(nlogn)。

桶排序可以说是分治思想的最好体现,它是排序算法中最简单和最快的,但桶排序可能会造成很大的空间消耗

桶排序比较适合用在外部排序中。所谓的外部排序就是数据存储在外部磁盘中,数据量比较大,内存有限,无法将数据全部加载到内存中。

2.效率分析

设n为元素数量,m为桶的数量,k为每个桶里的元素个数。假设元素均匀划分到m个桶中,则k=n/m。这里我们根据实际情况可知m<=n。

时间复杂度:在排序过程中,我们需要遍历整个元素序列,时间复杂度为O(n);在每个桶中假设使用快速排序,则时间复杂度为O(k* logk),那么m个桶排序的时间复杂度就为O(m* k* logk),当m接近n时,k约等于1,则O(m* k* logk)就是一个很小的常数,此时桶排序的时间复杂度接近O(n)。因此在额外空间充足的情况下,尽量增大桶的数量可以提高桶排序的速度。

空间复杂度:O(n+m)

桶排序的稳定性取决于桶内排序使用的算法。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值