简介

插入排序和比较排序是排序算法中比较基础和简单的两种,其时间复杂度均为

,在分析算法时间复杂度时,我们往往会只会分析比较开销,但是交换开销也确实存在。这里我将综合比较开销和交换开销,来分析一下插入排序和比较排序的区别,以及何时选择插入排序?何时该选择比较排序?

我之前的文章 排序算法详解 里给出了几个基本排序算法的JavaScript版本实现,感兴趣的也可以移步。

空间复杂度

插排和选排的均在交换时使用了一个临时空间,其空间复杂度均为

。而且插排和选排在排序时同时维护了一个已排序的有序列表和一个待排序的无序列表,不同在于:
  • 插排从无序列表中取第一个数,与有序列表的数依次比较,有序列表的已排数据的位置均可能发生变化。
  • 选排从无序列表中取最小数,只和无序列表中第一个数交换,此时无序列表第一个数归于有序列表(相当于最后一个数)。

在每一轮排序过程中,均需要有一个临时空间用来存储无序列表提取的这一个数,用于未来的交换。

时间复杂度

众所周知,插排和选排的时间复杂度均为

。我们在分析时间复杂度的时候,其实都是分析的比较时间复杂度,但是计算机做算法的时候除了比较,还有交换,并不是说交换时间复杂度不重要,而是它大部分情况相对于比较复杂度可以忽略,至于原因,接下来结合比较和交换开销,来分析插排和选排,自然就明白了

比较复杂度对比

  • 插入排序

    • 最差情况:最差情况下反向有序,每一轮插入,都需要依次比较到有序列表的第一个数,第一轮比较0次,第二轮比较1次,第N轮比较N-1次。一共比较

      次,复杂度
    • 最好情况:最好情况下有序,每一轮插入,都只需要比较1次,一共比较
      次,复杂度
    • 平均情况:平均情况下,每一轮插入,假设依次比较到有序列表的中间位置,一共比较
      次,复杂度
  • 选择排序选择排序比较次数是固定的,每一轮都需要从待排序的无序列表中选取一个最小(或最大)的数,选取中都需要比较到最后一个元素才能得到结果。第一轮比较N-1次,第N轮比较0次。一共比较

    次,复杂度

因此可以得出结论:在最差情况下,两者复杂度一样。在最好情况下,两者复杂度差异是比较大的(1个次方),而在平均情况下,插排的比较次数也只是选排的一半。这也是关于插排和选排的通用结论,一般情况下插排优于选排,主要就在于插排是插入有序列表,而选排是需要在无序列表中选择一个最大值(或最小值),想象一下我们斗地主摸牌,摸到一张牌我们是可以马上从小到大判断插入到哪的(这里假设只能从小到大比较),而不必每一张牌都对比一下。

但是上面的结论只讨论了比较复杂度,其实在为什么说平均情况下,插入排序比选择排序快? - 莫涛的回答 - 知乎 和Stack Overflow上,也有人对这种回答中不谈交换表示疑惑,下面我们再来分析一下交换复杂度。

交换复杂度对比

  • 插入排序

    • 最差情况:每一次比较完都需要交换。第一轮交换0次,第二轮交换1次,第N轮交换N-1次。一共交换

      次,复杂度
    • 最好情况:每一次比较完都无需交换,总共交换
      次,复杂度
    • 平均情况:每一轮都插入到中间位置,总共交换次数为
      次,复杂度
  • 选择排序

    • 最差情况:每一轮都需要交换,总共交换

      次,复杂度
    • 最好情况:每一轮都无需交换,总共交换
      次,复杂度
    • 平均情况:有一半轮次需要交换,总共交换
      次,复杂度

交换复杂度的对比中我们可以得出:最好情况下两者都无需交换,然而在最差和平均情况下,插入排序的交换次数都高于选择排序,差异为一个次方。可以看出差异还是很大的,单从这样来看,是无法忽略其影响的。

影响时间复杂度的其他因素

其实,在《算法导论》一书中还提到了一个算法性能分析依赖的以下要素:

  1. 待排项数
  2. 这些项已排序程度
  3. 项值的限制
  4. 计算机体系结构
  5. 使用的存储设备种类(主存,磁盘或磁带)

回到这个例子中,我们可以假设忽略硬件的影响、项值无限制。而已排序程度随机(也就是选用平均复杂度,不过一般算法分析都采用最坏情况下的复杂度作为瓶颈进行分析),因此分析要素只剩下待排项数N,可以使用上面的分析给出结论。

结论

插入排序和比较排序谁更优?主要在于比较开销和交换开销的量级:

  1. 如果两者量级相当,则插入排序优于选择排序
  2. 如果比较开销量级小于交换开销,则选择排序优于插入排序
  3. 如果比较开销量级大于交换开销,如果差别不大则难以比较,如果差异较大,则可以忽略交换复杂度,此时插入排序优于选择排序

事实上,交换一般直接交换内存地址(指针)而不是交换真实的数据,而比较则需要CPU的一些运算。这里的一个回答便给出了自定义赋值函数,如果直接交换数据,当数据量过大,交换开销大大增加,此时插入排序反而不如选择排序,因为其交换次数平均情况下和选择排序不在一个量级。

当然,由于交换排序进行了过多的交换次数(也就是写操作),如果使用Flash Memory,则需要额外注意,因为Flash Memory的擦除次数有限,过多的写操作会消耗其擦除次数,从而消耗Flash Memory的寿命。

总结 & 参考

一般情况下,插入排序确实优于选择排序,但也有需要注意的点,而不单单是只判断比较复杂度那么简单。需要我们了解清楚再做判断。

文章参考了以下资料:

  1. Insertion Sort vs. Selection Sort
  2. 为什么说平均情况下,插入排序比选择排序快? - 知乎
  3. When should one use Insertion vs. Selection sort?

请插入多卷集的最后一张磁盘_聊一聊插入排序和选择排序相关推荐

  1. 提示请插入多卷集的最后一张磁盘解决方法

      今天插上U盘就弹出了一个窗口提示请插入多卷集的最后一张磁盘解决方法 我点确定之后他继续弹出,点取消它也继续弹出,关掉一个又弹出来一个,有时候电脑硬盘读不出来,就是用着U盘的时候,过不久,硬盘全部不 ...

  2. 请插入多卷集的最后一张磁盘,然后单击”确认“继续

    当插入U盘时弹出"请插入多卷集的最后一张磁盘"怎么解决? 最近,每次插入U盘后,系统就会弹出如下的提示,怎么解决? 其实,很简单,就是把U盘里面所有的压缩文件(.zip和.rar等 ...

  3. 八大排序算法合集 (归并排序、交换排序、插入排序、选择排序......)

    目录 一.归并排序 二.交换排序 1.快速排序 2.冒泡排序 三.插入排序 1.直接插入排序(基于顺序查找) 2.折半插入排序(基于折半查找) 3.希尔排序(基于逐趟缩小增量) 四.选择排序 0.直接 ...

  4. 优盘提示插入多卷集的最后一卷解决办法(5)

    可能是优盘中有已经损坏的压缩文件,例如.zip文件已经损坏,这种情况下,Windows会提醒你插入另外一卷,即他认为你的压缩文件有一部分是在另外的存储设备上. 转载于:https://www.cnbl ...

  5. 计算机网络集线,一种基于计算机网络的自卷集线装置的制作方法

    本实用新型属于集线器.网络设施技术领域,更具体地说,特别涉及一种基于计算机网络的自卷集线装置. 背景技术: 集线器,集线器的英文称为"Hub"."Hub"是&q ...

  6. u盘显示请插磁盘f_教你自己解决U盘故障(磁盘不能打开并提示请插入磁盘)

    教你自己解决U盘故障(磁盘不能打开并提示请插入磁盘) 发布时间:2013-07-17 10:08:32   作者:佚名   我要评论 U盘不小心弄坏了,U盘故障是磁盘不能打开并提示"请插入磁 ...

  7. 换屏后sim卡显示无服务器,话机屏幕上显示“插入SIM卡”、“SIM卡无效”、“请插入UIM卡”,“无法获得网络服务”或“紧急呼叫”...

    **问题现象:** 插入SIM卡后,话机屏幕上显示"插入SIM卡"."SIM卡无效"."请插入UIM卡","无法获得网络服务&qu ...

  8. Android studio2.3小米8.5.1不能安装应用,没有MIUI优化,打开USB安装时提示“请插入SIM卡”,安装时手机没有任何反应,studio报Installation failed w

    今天升级了MIUI后,Android studio2.3小米8.5.1不能安装应用,手机红米2a,没有MIUI优化,打开USB安装时提示"请插入SIM卡",安装时手机没有任何反应, ...

  9. 计算机管理中少了一个H盘符,提示驱动器H中没有磁盘 请插入一张磁盘

    有时我们在使用U盘时会发现U盘出问题,这时电脑就会显示出让我们修复该U盘的提示.那360有修复U盘呢?答案当然是有的.今天小编就为朋友们介绍一下U盘常见的故障,具体的请看下面. 360u盘小助手独立版 ...

最新文章

  1. Qt修炼手册12_线程同步与线程等待条件
  2. 870C. Maximum splitting
  3. 如何查看本地的崩溃log_过年回家,还怕抢不到票?程序员教你如何抢票
  4. 开源运维管理软件排名_车主无忧:为什么放弃开源Kafka?
  5. JAVA内存结构解析
  6. Gmaill和MSN 8.0备忘
  7. Wide Deep 模型详解
  8. SpringMVC的乱码问题解决
  9. 8uftp链接linux,8UFTP工具,FTP工具连接的办法,配置方式
  10. 【个人笔记】Ubuntu18.04 安装显卡驱动
  11. 上传视频到FTP服务器+播放
  12. nodejs mysql process_nodeJS之进程process对象
  13. Mac上启动、关闭、重启MySQL服务
  14. 微信小程序如何刷新当前页面或者刷新上一个页面
  15. 10年测试,告诉你常见的软件测试类型有哪些?
  16. 新型红包套路,论推广和运营,灰产们真是一把好手
  17. 延时1s的程序设计c语言,C语言延时程序.doc
  18. 传统大数据平台的一些常见问题
  19. 马来西亚央行_马来西亚-第-1天总结
  20. 热带气旋强度估计——物理信息融合

热门文章

  1. 使用ConcurrentLinkedQueue惨痛的教训
  2. 算法导论————斜率优化
  3. Ruby中的字符串与符号
  4. 2013年上半年项目总结
  5. android studio 经验
  6. linux防火墙安装httpd配置,CentOS7下 Apache的安装配置方法
  7. vue改变标签属性_Vue用v-for给循环标签自身属性添加属性值的方法
  8. python的knn算法list_【风马一族_Python】 实施kNN算法
  9. 数据 正则化 python_Python数据科学:正则化方法
  10. 感恩节日海报设计模板|简洁优雅的花卉主题海报