【算法实现】counting sort

MIT的算法视频今天看到了lecture05,前半部分利用决策树,总结了所有比较类排序算法(插入排序、归并排序、快速排序、堆排序等)的时间复杂度至少为nlgn,就是说,如果我们采用比较类排序算法,那最快的也就是nlgn,归并、堆、随机快速排序这些都是nlgn。那么,nlgn就是排序的极限效率了吗?当然不,课程接下来介绍的counting sort,将时间复杂度降低到了线性时间,so exciting!!!

 

counting sort

for i ← 1 to k
do C[i] ← 0
for j ← 1 to n
do C[A[ j]] ← C[A[ j]] + 1 x3; C[i] = |{key = i}|
for i ← 2 to k
do C[i] ← C[i] + C[i–1] x3; C[i] = |{key ≤ i}|
for j ← n downto 1
do B[C[A[ j]]] ← A[ j]
C[A[ j]] ← C[A[ j]] – 1

 

要理解这个伪代码并不难,需要做的就是举个例子画个图;这里我比较关心的主要有两点:

1. 最后一个loop,及for j ← n downto 1,为什么不直接根据array C的结果顺序读入A的各值插入到最终的B,而是要从A的最后一个值开始一个一个的查看;这也是视频中一个TA提的疑问;

2. 数组C的大小由A中最大一个数值决定,那在实际操作中会有一些负面的影响,比如,我没有足够的内存,或者需要排序的数组A很稀疏,那么C中很多空间其实就浪费了……

 

关于第二个疑问,目前我还没有想得太明白怎么去解决,不过在想第二个疑问时帮助我解答了第一个疑问。

 

我是这样想的,从A的最后一个值开始查看,让我们在最终确定顺序时比较的次数由A的个数n决定,如果根据C的结果直接排序,我们的比较次数将由A的最大值,也就是C的个数k来决定;这样,在A比较稀疏,又存在一个或多个超大值时,k将会异常的大,而counting sort的时间复杂度为n+k,也就是说它依赖于k,并且,只有当n和k差不多相似时(around the same),counting sort才是线性的,如果我们最后的loop也依赖k,将会增大非线性时间复杂度的概率,所以,从A的最后一个值开始查看并排序将是一个比较好的选择。

 

课程最后讲了radix sort,这个算法属于counting sort的一种,但比上面介绍的counting sort更让人兴奋,因为它能在排序个数n为polynomial size的情况下仍然保持线性时间复杂度,这是个古老的算法,古老到计算机还没出现时就已经有了,不过这个算法真的太棒了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值