桶排序(Bucket sort)

桶排序又称箱排序(Bucket sort),是一个排序算法,工作的原理是将数组分到有限数量的桶里。每个桶再个别排序(可能在使用其他的排序算法),最后依次把各个桶中的记录列出来便得到了有序序列。桶排序是基数排序的一种归纳结果。当要被排序的数组内的数值平局分配的时候,桶排序使用线性时间( Θ ( n ) \Theta(n) Θ(n))。但桶排序并不是比较排序,它不受 O ( n l o g n ) O(n{\bf log}n) O(nlogn)的时间复杂度影响。

基本思想

桶排序的想法近乎彻底的分治思想。桶排序假设数组均匀分布在一个范围内,并将这一范围划分为几个子范围(桶)。然后利用某种映射函数 f f f,将待排序的关键字 k k k映射到下标为 i i i的同种,那么该关键字 k k k就作为 B [ i ] B[i] B[i]中的元素。接着对每个桶的元素进行排序,并将其依次输出即可得到一个有序的序列。

映射函数一般采用 f = a r r [ i ] / k f=arr[i]/k f=arr[i]/k,其中 k = n k=\sqrt{n} k=n

如果要是桶排序更加高效可以注意下面两点:

  1. 在额外空间足够的情况下,增大桶的数量。
  2. 使用的影射函数尽量能够将输入的 n n n个数据均匀分配到 k k k个桶中。
  3. 注意桶内元素排序采用的算法,它对性能的影响至关重要。

具体的流程为:

  1. 设置与一个定量的数组当作空桶。
  2. 寻访序列,并把元素利用映射函数放入桶中。
  3. 对每个非空的桶进行排序。
  4. 从非空的同种将元素一次取出得到排列之后的结果。

代码实现

public class Template {

    public void bucketSort(double[] arr) {
        int len = arr.length;
        ArrayList<LinkedList<Double>> buckets = new ArrayList<>();
        for (int i = 0; i < 10; i++) buckets.add(new LinkedList<>());
        for (double val : arr) insert(buckets.get(mapping(val)), val);

        int ind = 0;
        for (LinkedList<Double> bucket : buckets) {
            for (Double val : bucket) {
                arr[ind++] = val;
            }
        }
    }

    /**
     * 映射函数
     *
     * @param val
     * @return
     */
    public int mapping(double val) {
        return (int) val;
    }

    public void insert(List<Double> bucket, double val) {
        ListIterator<Double> it = bucket.listIterator();
        boolean flag = true;
        while (it.hasNext()) {
            if (val <= it.next()) {
                it.previous();
                it.add(val);
                flag = false;
                break;
            }
        }
        if (flag) it.add(val);
    }

    public static void main(String[] args) {
        Template temp = new Template();
        double[] arr = {0.12, 2.2, 8.8, 7.6, 7.2, 6.3, 9.0, 1.6, 5.6, 2.4};
        temp.bucketSort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

参考文献:

  1. 【算法】排序算法之桶排序
  2. Java 桶排序,详细分析
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值