九 桶排序

此博客用于个人学习,来源于算法的书籍和网上的资料,对知识点进行一个整理。

1. 概述:

桶排序 是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。 桶排序 (Bucket sort)的工作的原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用 桶排序 进行排)。

2. 算法:

  • 创建这些桶,确定每一个桶的区间范围:区间跨度(大小) = (最大值-最小值)/ (桶的数量 - 1)
  • 遍历原始数列,把元素对号入座放入各个桶中
  • 每个桶内部的元素分别排序(显然,只有第一个桶需要排序)
  • 遍历所有的桶,输出所有元素

3. 代码实现:

/**
 * 桶排序
 */
public class BucketSort {

    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 i = 0; i < bucketNum; i++){
            bucketList.add(new LinkedList<Double>());
        }

        //3.遍历原始数组,将每个元素放入桶中
        for (int i = 0; i < array.length; i++){
            int num = (int)((array[i] - min)  * (bucketNum- 1) / d);
            bucketList.get(num).add(array[i]);
        }

        //4.对每个通内部进行排序
        for (int i = 0; i < bucketList.size(); i++){
            //JDK底层采用了归并排序或归并的优化版本
            Collections.sort(bucketList.get(i));
        }

        //5.输出全部元素
        double[] sortedArray = new double[array.length];
        int index = 0;
        for (LinkedList<Double> list : bucketList){
            for (double element : list){
                sortedArray[index] = element;
                index++;
            }
        }
        return sortedArray;
    }
}

4. 特点:

  1. 优点:在取值范围不是很大的情况下,它的性能甚至快于 O(nlgn) 的排序算法,并且元素并不要求都为整型。

  2. 缺点: 桶排序 对数据的条件有特殊要求,适合元素值集合并不大的情况。

5. 算法分析:

  1. 时间复杂度:

    第一步求数列最大最小值,运算量为 n。

    第二步创建空桶,运算量为 m。

    第三步遍历原始数列,运算量为 n。

    第四步:一共有 m 个桶,每个桶内部使用了 O(nlogn)的排序算法做排序,每个桶的元素平均有 n/m 个(即:数据规模为 n/m),所以运算量为 m * (n/m) * log(n/m ) 。

    第五步输出排序数列,运算量为 n。

    加起来,总的运算量为 3n+m+ n/m * log(n/m ) * m = 3n+m+n(logn-logm) 。去掉系数,时间复杂度为:O(n+m+n(logn-logm))

  2. 空间复杂度:空桶占用的空间 + 数列在桶中占用的空间 = O(m+n)。

  3. 稳定性 :由于其中使用了 list 的数据结构,使得大小相等的两个元素相对位置不变,是稳定的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值