数据结构—桶排序学习笔记

数据结构—桶排序学习笔记

应用场景

数列取值范围过大,或者不为整数时,不再适用计数排序,升级为桶排序来进行排序。

题型:大数据时代:本月某网站播放数量前十的视频,视频数量又多、播放次数差别又大,非常适合桶排序。

算法原理

类别于计数排序中计数数组的某一个元素,桶排序中的每一个桶代表了一个区间范围,里面可以承载一个或多个元素。桶排序的第一步就是创建这些桶,并确定每一个桶的区间范围。

举例:2.2,0.5,5.5,4.24,0.54,3.36 

具体创建多少个桶,如何确定桶的区间范围,有很多不同的方式。面对少量数据,可以创建和原始数据量相同的桶数量,除了最后一个桶只包含数列的最大值,其余的每个桶的区间按比例分配。
区间跨度 = ( 最大值 - 最小值 ) / ( 桶的数量 - 1 )

桶数:6
区间跨度 = ( 5.5 - 0.5 ) / ( 6 - 1) = 1
桶区间:[0.5,1.5),[1.5,2.5),[2.5,3.5),[3.5,4.5),[4.5,5.5),[5.5,5.5]

桶排序的第二步就是遍历原始数列,然后把元素对号入座放入各个桶中。

比如 0.5 放入第一个桶,2.2 放入第二个桶,5.5 放入最后一个桶,依次类推,注意区间开闭
桶一:0.5,0.54                    桶二:2.2
桶三:3.36                         桶四:4.24
桶五:无                           桶六:5.5

桶排序的第三步就是对桶内元素分别排序即可。桶内排序在数据量较小时可以使用 直接插入排序 ,数据量较大时使用 快速排序

比如这里只需要对第一个桶进行排序,得到第一个桶里顺序为 0.5,0.54

桶排序的第四步就是按顺序遍历所有桶,输出其中的所有元素。

最后的顺序为0.5,0.54,2.2,3.36,4.24,5.5

复杂度

对于 n 个数据,我们创建 m 个桶进行排序,则它的:

  • 时间复杂度:
    ①遍历求最大值,O(n);
    ②创建m个空桶,O(m);
    ③遍历原始序列,O(n);
    ④每个桶内部排序,运算量为 m*(n / m)*log(n / m) ,即时间复杂度为 O(n(logn - logm)) ,当然,这是在序列在桶间分布非常均匀的情况下
    ⑤输出排序后的序列,O(n);
    总的时间复杂度为 O(3n + m + n(logn - logm))

    因此:
    在最好的情况下,n 个数据创建 n 个桶,每个桶内都装一个元素,可知算法的时间复杂度为 O(3n+n+n(logn - logn)),即退化为 O(n) 时间复杂度
    在最坏的情况下,n 个数据创建 m 个桶,除了最后一个桶有最大值外,其余数据全部集中在第一个桶内,则第一个桶内排序时间复杂度为 O(n * logn) ,即退化为 O(n * logn) 时间复杂度,还会多创建 m - 2 个空桶。

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

代码实现

public void bucketSort(double[] nums){
    double max = nums[0],min = nums[0];
    //第一趟遍历,获得最大值和最小值
    for(int i=1;i<nums.length;i++){
        if(nums[i] > max)
            max = nums[i];
        if(nums[i] < min)
            min = nums[i];
    }
    //获取跨度值
    double d = max - min;
    //创建桶
    int bucketNum = nums.length;
    ArrayList<LinkedList<Double>> bucketList = new ArrayList<>();
    for (int i=0;i<bucketNum;i++){
        bucketList.add(new LinkedList<Double>());
    }
    //将数字放入对应桶中
    for(double num:nums){
        //复杂度为O(1)的判断操作
        int bucketNo = (int)((num-min)*(bucketNum-1)/d);
        bucketList.get(bucketNo).add(num);
    }
    //对每个桶内元素进行排序
    for(LinkedList<Double> list : bucketList){
        Collections.sort(list);
    }
    //将原数组进行排序输出
    int index = 0;
    for(LinkedList<Double> list : bucketList){
        for(double num:list){
            nums[index++] = num;
        }
    }
}

这里判断数字位于哪个桶中的方法,复杂度是O(1),需要记住这个方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值