数据结构与算法 / 排序算法(3)

一、桶排序(Bucket sort)

1、原理

将要排序的数据分到几个有序的桶里,每个桶里的数据再进行排序。桶内的数据排序完毕之后,再把桶里的数据依次取出,组成的序列就是有序的了。

2、原地排序?

属于原地排序算法。主要看桶内排序是否时原地排序算法,若选择插入排序,则桶排序就是属于原地排序,若选择了快速排序,则不属于原地排序。

3、稳定性算法?

不属于稳定性排序算法。因为根据我的代码实现,桶内数据会申请内存,故空间复杂度为O(n)。

4、时间复杂度

(1)最好情况

桶数量很多,并且数据均匀分布在各个桶内。

假设要排序的数据数量为 n,分配的桶的个数为 m,那么每个桶中的数据的数量为 k = n / m 。桶内采用快速排序算法,根据之前的推到,快排的时间复杂度为O(nlogn),准确说应该是

C是常数。将 k 代入公式中,得到每个桶的排序时间为

将 k 的计算公式带入上述公式中,得到如下

m 个桶一共需要的时间为

当 m 接近于 n 时,上述公式就变为如下

所以时间复杂度为 O(n)

(2)最坏情况

数据只分配到了一个桶,算法退化成快排,时间复杂度为 O(nlogn)

5、数据要求

  • 要排序的数据要轻松地划分成 m 个桶,并且桶与桶之间要有天然的大小顺序。
  • 数据在各个桶内的分布是均匀的。

6、适用场景:外部排序(数据保存在外部磁盘中,数据量比较大,内存有限,无法将数据全部加载到内存中)

假设有10G的订单数据,如何按照订单金额从小到大进行排序?

步骤如下:

  • 扫描一遍订单,确定金额的最小值和最大值,假设分别为 1 和 10k 。
  • 将订单金额分成100个桶,编号分别为 01,02,03,……,那么第 1 个桶内的金额为 1 ~ 1000,第 2 个桶内的金额为 1001 ~ 2000,……
  • 每个桶内的数据大概为100M,加载到内存中进行快排是没有问题的,将排序结果按照桶编号依次存入一个固定文件中,那么该文件中最后显示的结果就是最终的排序结果。

二、计数排序(Counting sort)

1、原理

当要排序的数据 n 非常大时,而数据所处的范围又较小,比如最小值和最大值分别为 1 和 k ,那么可以把数据分成 k 个桶,每个桶内的数据都是相同的,从而节省了桶内的排序时间。

实际上计数排序是桶排序一种特殊情况,即:对于桶排序,每个桶内的数据需要进行排序,而计数排序的桶内数据都是相同的,不需要排序。

2、原地排序?

不属于原地排序算法。根据代码的实现原理,需要使用计数数组,所以空间复杂度为 O(n) 。

3、稳定性算法?

属于稳定性排序算法。因为在将数据放入桶中时,保持原有数据顺序,再复原时按照顺序复原可以。

4、时间复杂度

根据算法的实现原理,只需要遍历一遍数据即可,时间复杂度为 O(n)

5、应用栗子

       如何将某省100万的考生的高考成绩从小到大排序?

分数范围为 0 ~ 900,每一分都有大量考生重合。可以将分数分成 901 个桶,桶内的分数都是相同,只需要遍历数据, 将数据放入各个桶内即可。

6、适用范围

  • 数据范围不大,即:数据量要远大于数据范围。
  • 数据只能给非负整数进行排序

三、基数排序(Radix sort)

1、原理

将待排序的数列中的数拆分成“位”(十进制),对每一位进行稳定性排序(例如计数排序),直到所有的位都排序完成。

2、原地排序?

不属于原地排序算法。因为各个位排序时使用了线性排序算法。

3、稳定性排序?

属于稳定性排序。因为针对每一位的操作实际上都是稳定性排序,保证了相同数据的前后位置。

4、时间复杂度

因为对每一位的排序采用计数排序,时间复杂度为 O(n),假设最大的数据所在的位(十进制)总数为 k,则时间复杂度为O(kn),总体来说时间复杂度约等于 O(n)

5、应用栗子

如何对 10 万个手机号码你进行从小到大排序?

这里可以采用基数排序算法,将所有的手机号码拆成11个数字,从后向前一次进行计数排序,因为计数排序属于稳定性 性算法,这就保证了最终的排序结果是正确的。

6、适用范围

  • 可以将待排序的数据拆成“位”来比较,“位”与“位”之间存在递进关系。
  • 每一位的数据范围不能太大,这样可以使用线性排序算法来排序,例如计数排序。

四、总结

1、性质

算法种类时间复杂度空间复杂度原地排序稳定性排序
桶排序O(n)O(n)××
计数排序O(n)O(n)××
基数排序O(n)O(n)××

2、源代码

Github

 

参考:极客时间《数据结构与算法之美》王争

这门课真心推荐,内容很经典、栗子很形象,里面还包含了很多面试题目。真是居家旅行必备良药。

(SAW:Game Over!)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值