算法学习(13)四种常用排序算法比较和选择 (内含运行时间比较)

前言

这部分内容理论部分来自于教材。出乎我意料的是,排序算法,再怎么变,基本都是 O ( n 2 ) O(n^2) O(n2) 的复杂度,只有快排和推排序法,因为一些巧妙的设计,稍微有了提升。这篇博客会增加各种排序法对同一组数据排序的比较。使用运行时间来比较,应该是最直观的方式。

理论分析

准备知识

衡量一个算法的优劣,一般是从时间和空间两个维度(这正是程序优化要协调的两个维度

时间维度,一般考虑计算复杂度,用 O ( n ) O(n) O(n) O ( n 2 ) O(n^2) O(n2)等来衡量
空间维度,一般考虑对计算机内存及其他资源的使用。不过对于现代计算机来说,内存什么的,都认为是够用的。所以,这里着重考虑时间维度的优化。

各算法的时间复杂度

算法回顾:

  1. 快排,冒泡法 (传送门
  2. 简单选择排序,堆排序法(传送门

结论

  1. 冒泡排序法:平均速度最坏情况的速度都是 O ( n 2 ) O(n^2) O(n2)
  2. 快速排序法:平均速度为 O ( n log ⁡ n ) O(n \log n) O(nlogn),最坏情况(数组一开始是有序,不过是从大到小), O ( n 2 ) O(n^2) O(n2) log ⁡ \log log的底数为2)
  3. 简单选择排序法:平均速度最坏情况的速度都是 O ( n 2 ) O(n^2) O(n2)
  4. 堆排序法:平均速度最坏情况的速度都是 O ( n log ⁡ n ) O(n \log n) O(nlogn)

书中说,没有一种是最优的,得根据实际应用场景,这很有道理。因为具体使用的时候,我们得考虑数据是否基本有序,或是程序可用的存储空间,或是是否限制数据移动次数。不过,理论总是抽象的,还是直接上代码看效果吧

前期准备:数组复制

为了客观评价各个算法的运行速度,需要对同一个数组进行排序,所以,对于原始的数组,我们要产生多份,用于各种不同的排序。不过,这里有个误区

a = [1,4,5]
b = a

上面只是把 a a a 存储的指向数组的地址给了 b b b, 此时 a , b a, b a,b指向是同一个数组,修改其中一个,另一个也会受影响,如果 a a a 被排序好了, b b b 也会是有序的。这时候,要使用 list() 函数。效果见下图
数组复制
更多关于数组复制,请参考这里

程序运行分析

1. 长度为500的数组,数字范围 [ 1 , 100000 ] [1, 100000] [1,100000]

500的比较

分析

对于快排和堆排序,这两种非 O ( n 2 ) O(n^2) O(n2)复杂度的,排数字小的,测不出时间。
选择排序,看起来比冒泡快。

2.长度为5000的数组,数字范围 [ 1 , 100000 ] [1, 100000] [1,100000]

5000的比较

分析

**开始有趣了!**目前快排和堆排依然不相上下,但是冒泡法已经掉队,而选择排序还在苦苦支撑。

3. 长度为50000的数组,数字范围 [ 1 , 100000 ] [1, 100000] [1,100000]

50000

分析

终于分出胜负了!

因为我们实验的数据,是完全随机的,所以,快排真的超级有优势的。我以前其他地方也试过快排,但因为数据基本有序,快排体现不出它的优势。

堆排落后了点,但依然还是表现优秀。

冒泡法,完全掉队了,4分多钟……

选择排序,看起来还Ok,但已经很差了……

其实不用感到惊讶,这从复杂度分析就可以感觉出来了。

数字展示

对于 10000 个数的排序,复杂度为 O ( n 2 ) O(n^2) O(n2)的,就是 1000 0 2 = 1 0 4 10000^2=10^4 100002=104 (1亿, 可以理解为1亿个操作步骤), 而对于 O ( n log ⁡ n ) O(n \log n) O(nlogn), 是 10000 × log ⁡ 2 10000 = 1.3 × 1 0 5 10000\times\log_2 10000=1.3\times10^5 10000×log210000=1.3×105 (13万,同样的数组,只需要13万个操作即可,当然快了!)

总结

第一次把4个排序算法摆一起比较,超级好玩!也感受到了算法分析的魅力,上面的复杂度,是完全数学分析出来的!

使用中,优先推荐大家使用 快排堆排(当然,前提是数据是足够乱,越乱越体现优势~)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值