基数排序为什么要从个位开始_为什么说 O(n) 复杂度的基数排序没有快速排序快?...

(给算法爱好者加星标,修炼编程内功)

作者:帅地  (本文来自作者投稿)

跟着西瓜兄弟学算法

85d37f8f9e8fcd428df6605c8d2b331f.png
15614fe78a9024e107742564faba5769.png
e36213f367a625b300883c752d6062fc.png
dc11e9569be6bbb2e629082d8cb55acf.png
26a48013f06a3bfdf4fc85aa9777dd80.png
80ad9502d61710d47ac630819df16888.png
53888ef3f61b7599ec4f75fd14a48174.png

老大:我简单给你讲下吧,你学过那么多排序,估计一看就懂了。基数排序,是一种基数“桶”的排序,他的排序思路是这样的:先以个位数的大小来对数据进行排序,接着以十位数的大小来多数进行排序,接着以百位数的大小……

排到最后,就是一组有序的元素了。不过,他在以某位数进行排序的时候,是采用“桶”来排序的,基本原理就是把具有相同个(十、百等)位数的数放进同一个桶里。我直接给你个例子吧,保证你一看就懂。

例如我们现在要对这组元素来排序:

742ba626bbb67fe8ff4d9f18d9e03432.png

由于我们是以每个数的某位数来排序的,这位数的范围是0-9,所以我们需要10个桶。

de79c0853910ba0be8a5f0a023f84ddb.png

第一遍,先以个位数排序,把具有相同个位数的数放进桶里,结果如下:

e4a3ddf907a595daa5381e2f94ccee2c.png

之后再按照从0号桶到9号桶的顺序取出来,结果如下

410fa43447bf8e725c4547bbc1792ee6.png

个位数排序完成。

第二遍,以十位数来排,结果如下:

ad5bf651fe6d39a75c1c6f52f314107a.png

再取出来放回去:

37c6f643f1c1394b57c299c16bafe74b.png

十位数排序完成,最终的结果就是一组有序的元素。如果元素中有百位数的话,大不了就按照百位数再给他重复排一遍。

9fffb344e61e7afa298cb7b443b15718.png
51b5df10cd1acfe142a858b0799474de.png
d29958cc299dbff69bf09faf0454a5c4.png

老二:那我想问下,为啥要从个位数开始排序呢?可以直接从最高位开始排序吗?如果从最高位开始排序的话,如果一个数最高位比另一个数大,那么这个数就一定比另外一个数大了,不用在比较次高位了。这样的话,不是可以排的更快吗?

2edf340239848cc260e2f6d35eb36f8d.png

老大:脑子反应的挺快啊。是的,是可以以最高位来排序的,而且也像你说的,以最高位来排序的话,是可以减少数据之间比较的次数。但我们仍然不建议以最高位来排序,因为他有个致命的缺点

730703f65f1fa712206913d93a836771.png
80f0754184b5814152ec5768b4896a27.png

老大:还是以刚才那个例子吧,我们一边用最高位来排序,一边来寻找这个致命的缺点。数组如下(元素的顺序改变了一些):

20943ebb388167d2543ce9f8fdb4ac1b.png

第一遍:最高位十位数排序,结果如下(有些没用到的桶给省略了):

12eb693e0247a0362bed1d727acbe4d2.png

显然,不在桶一个桶里的数,他们的大小顺序已经是已知的了,也就是说,右边桶的数一定比左边桶的数大,所有在接下来的个位数排序里,我们只需要进行“各部分”单独排序就可以了,每一小部分都类似于原问题的一个子问题,做的时候可以采用递归的形式来处理。

9874339b21a63dfe6188d35f5244a89e.png

最后汇总,即可完成排序:

f3f90c1a67e606310b85d61b19ab6116.png

这种方法确实可以减少比较的次数,不过请大家注意,在每个小部分的排序中,我们也是需要10个桶来将他们进行排序,最后导致的结果就是,每个不同值的元素都会占据一个“桶”,如果你有1000个元素,并且1000个元素都是不同值的话,那么从最高位排序到最低位,需要1000个桶。

这样子的话,空间花费不仅大,而且看起来有点背离基数排序最初的思想了(“背离”这个词,个人感觉而已)。所以,我们一般采用从最低位到最高位的顺序哦。

493787af639738cedbe1e9f5d583fce4.png

关于基数排序,还有以下几个问题,你不妨也想一想?

1、基数排序是一种用空间换时间的排序算法,数据量越大,额外的空间就越大?

我的想法:我觉得基数排序并非是一种时间换空间的排序,也就是说,数据量越大,额外的空间并非就越大。因为在把元素放进桶的时候,是完全可以用指针指向这个元素的,也就是说,只有初始的那些桶才算是额外的空间。

2、居然额外空间不是限制基数排序速度的原因,那为啥基数排序没有快速排序快呢?

基数的时间复杂度为O(n),不过他是忽略了常数项,即实际排序时间为kn(其中k是常数项),然而在实际排序的过程中,这个常数项k其实是很大的,这会很大程度影响实际的排序时间,而像快速排序虽然是nlogn,但它前面的常数项是相对比较小的,影响也相对比较小。

需要说明的是,基数排序也并非比快速排序慢,这得看具体情况,(不要被标题所影响哈)。而且,数据量越大的话,基数排序会越有优势。

3、有人可能会问,说了这么多,那到底是基数排序快还是快速排序快呢?

对于这样的问题,我只能建议你,自己根据不同的场景,撸几行代码,自己测试一下。

如果你问我,哪个排序在实际中用的更多,那么,我选快速排序。

【本文作者】

帅地:一名热爱编程的在校生,目前维护订阅号「苦逼的码农」,专注于写于编程相关的文章

推荐阅读

(点击标题可跳转阅读)

人人都能读懂的编译器原理

算法有偏见么?

广播路由算法: 我是如何优雅着把悄悄话带给其他人的

觉得本文有帮助?请分享给更多人

关注「算法爱好者」加星标,修炼编程内功

ba4d800c963b3dc64a0ff3f6819a62f4.png

喜欢就点一下「好看」呗~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值