算法学习笔记(十一)

一、桶排序
桶排序同样是一种线性时间的排序算法,类似于计数排序所创建的统计数组,桶排序需要创建若干个桶来协助排序。
桶(bucket) 代表一个区间范围,里面可以装载一个或者多个元素。

假设有一个非整数数列:

如下图

工作原理:
第一步:
创建桶,并确定每一个桶的区间范围。

具体创建多少个桶,如何确定桶的区间范围,有很多种不同的方式,这里创建桶的数量等于原始数列的元素数量,除最后一个桶只包含数列最大值外,前面各个桶的区间按照比例来确定

	**区间跨度=(最大值-最小值)/(桶的数量-1)**

第二步:

遍历原始数列,把元素对号入座放入到各个桶中。

第三步
对每个桶内部的元素分别进行排序。

第四步
遍历所有的桶,输出所有元素。
到此为止,排序结束。
代码:

public class bucket {
    public  static double[] bucketSort(double[] array){
        //1.得到数列的最大值和最小值,并计算出差值。d
        double max = array[0];
        double min = array[0];

        for (int i = 1; i <array.length ; i++) {
            if (array[i]>max){
             max= array[i];
            }
            if (array[i]<min){
                min = array[i];
            }
        }
        double d  =max - min;
            //2,初始化桶
            int bucketNum = array.length;
            ArrayList<LinkedList<Double>> bucketList = new ArrayList<LinkedList<Double>>(bucketNum);
            for (int j = 0; j <bucketNum ; j++) {
                bucketList.add(new LinkedList<Double>());
            }
            //3,遍历原始数组,将每个元素放入桶中
            for (int j = 0; j <array.length ; j++) {
                int  num = (int)((array[j]-min)*(bucketNum-1)/d);
                bucketList.get(num).add(array[j]);
            }
            //4,对每个桶 内部进行排序
            for (int j = 0; j <bucketList.size() ; j++) {
                //JDK底层采用了归并排序或者归并的优化版本
                Collections.sort(bucketList.get(j));
            }
            //5,输出全部元素
            double[] sortArray = new double[array.length];
            int index = 0 ;
            for (LinkedList<Double> list :bucketList) {
                for (double element:list) {
                    sortArray[index] = element;
                    index++;
                }
            }
            return sortArray;
    }

    public static void main(String[] args) {
        double[] array = new double[]{4.12,6.421,0.0023,3.0,2.123,8.122,4.12,10.09};
        double[] sortArray = bucketSort(array);
        System.out.println(Arrays.toString(sortArray));
    }
}

结果:
在这里插入图片描述

在上述代码中,所有的桶都保存在ArrayList集合中,每一个桶都被定义成一个链表,这样便于在尾部插入元素。同时上述代码使用了JDK的集合工具类Collections.sort来为桶内部的元素进行排序。它的底层采用的是归并排序或Timsort,可以把他们当作一个时间复杂度为O(nlogn)的排序。

二,桶的时间复杂度

假设原始数列有n个元素,分成n个桶。
第一步,求数列最大、最小值。运算量为n.
第二步,创建空桶,运算量为n。
第三步,把原始数列的元素分配到各个桶中,运算量为n。
第四步,在每个桶内部做排序,在元素分布相对均匀的情况下,所有桶的运算量之和为n.
第五步,输出排序数列,运算量为n。
因此桶排序的时间复杂度为o(n)。同样空间复杂度也是o(n)。
当然桶排序并非绝对稳定,在极端情况下,第一个桶中有n-1个元素,最后一个桶中有1个元素,此时的时间复杂度将会退化为o(nlogn),并创建了许多空桶。因此需要看具体的场景来选择算法。

消化消化,对比一下之前所学习的排序。

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值