前言:

首先清楚何谓稳定性?


通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。在简单形式化一下,如果Ai = Aj,Ai原来在Aj位置前,排序后Ai还是要在Aj位置前。

判断方法:

对于不稳定的排序算法,只要举出一个实例,即可说明它的不稳定性;而对于稳定的排序算法,必>须对算法进行分析从而得到稳定的特性。需要注意的是,排序算法是否为稳定的是由具体算法决定的,不稳定的算法在某种条件下可以变为稳定的算法,而稳定的算法在某种>条件下也可以变为不稳定的算法。

常见算法的稳定性:

堆排序、快速排序、希尔排序、直接选择排序是不稳定的排序算法,而基数排序、冒泡排序、直接插入排序、折半插入排序、归并排序是稳定的排序算法。

排序的好处:

1、如果只是简单的进行数字的排序,那么稳定性将毫无意义。
2、如果排序的内容仅仅是一个复杂对象的某一个数字属性,那么稳定性依旧将毫无意义(所谓的交换操作的开销已经算在算法的开销内了,如果嫌弃这种开销,不如换算法好了?)
3、如果要排序的内容是一个复杂对象的多个数字属性,但是其原本的初始顺序毫无意义,那么稳定性依旧将毫无意义。
4、除非要排序的内容是一个复杂对象的多个数字属性,且其原本的初始顺序存在意义,那么我们需要在二次排序的基础上保持原有排序的意义,才需要使用到稳定性的算法,例如要排序的内容是一组原本按照价格高低排序的对象,如今需要按照销量高低排序,使用稳定性算法,可以使得想同销量的对象依旧保持着价格高低的排序展现,只有销量不同的才会重新排序。(当然,如果需求不需要保持初始的排序意义,那么使用稳定性算法依旧将毫无意义)。

阐述八大排序稳定性的产生:

(1)冒泡排序
冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。

(2)选择排序

选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给>二个元素选择第二小的,依次类推,直到第n-1个元素,第n个 元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么 交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9, 我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。

(3)插入排序
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开 始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相 等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳 定的。

(4)快速排序

快速排序有两个方向,左边的i下标一直往右走,当a[i] <= a[center_index],其中center_index是中枢元素的数组下标,一般取为数组第0个元素。而右边的j下标一直往左走,当a[j] > a[center_index]。如果i和j都走不动了,i <= j, 交换a[i]和a[j],重复上面的过程,直到i>j。 交换a[j]和a[center_index],完成一趟快速排序。在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为 5 3 3 4 3 8 9 10 11, 现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j] 交换的时刻。

(5)归并排序

归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有 序的长序列,不断合并直到原序列全部排好序。可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定 性。那么,在短的有序序列合并的过程中,稳定是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结 果序列的前面,这样就保证了稳定性。所以,归并排序也是稳定的排序算法。

(6)基数排序

基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优 先级排序,最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以其是稳定的排序算法。

(7)希尔排序(shell)
希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小, 插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元 素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。

(8)堆排序
我们知道堆的结构是节点i的孩子为2i和2i+1节点,大顶堆要求父节点大于等于其2个子节点,小顶堆要求父节点小于等于其2个子节点。在一个长为n 的序列,堆排序的过程是从第n/2开始和其子节点共3个值选择最大(大顶堆)或者最小(小顶堆),这3个元素之间的选择当然不会破坏稳定性。但当为n /2-1, n/2-2, …1这些个父节点选择元素时,就会破坏稳定性。有可能第n/2个父节点交换把后面一个元素交换过去了,而第n/2-1个父节点把后面一个相同的元素没 有交换,那么这2个相同的元素之间的稳定性就被破坏了。所以,堆排序不是稳定的排序算法。

各排序算法的时间复杂度:


注:快速排序的空间复杂度为O(logn)~O(n)

参考来自:排序算法的稳定性,排序算法的稳定性及其意义

八大排序算法的稳定性及时间复杂度相关推荐

  1. 12八大排序算法的稳定性以及时间空间复杂度总结

    文章目录 一.排序的稳定性 二.八种排序方式的复杂度和稳定性 三.总结 一.排序的稳定性 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中 ...

  2. 排序算法【稳定性+空间复杂度+时间复杂度(平均、最好、最坏)】

    ​​​​​​​ 演示网址:https://www.cs.usfca.edu/~galles/visualization/  

  3. 冒泡和快速排序的时间复杂度_八大排序算法性能分析及总结

    一.排序算法说明 排序的定义:对一个无序的序列进行排序的过程. 输入:n个数:a1,a2,a3,-,an. 输出:n个数的排列:a1,a2,a3,-,an,使得a1<=a2<=a3< ...

  4. 八大排序算法稳定性分析

    八大排序算法稳定性分析 稳定性定义: 排序前后两个相等的数相对位置不变,则算法稳定. 稳定性的好处: 从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用. 各排序算法的稳 ...

  5. 八大排序算法稳定性分析,原来稳定性是这个意思...

    点击上方蓝字"轮子工厂"关注公号 后台回复"我要造轮子"获取100本经典图书 稳定性定义: 排序前后两个相等的数相对位置不变,则算法稳定. 稳定性得好处: 从一 ...

  6. 八大排序算法时间复杂度对比

    八大排序算法时间复杂度对比

  7. 冒泡和快速排序的时间复杂度_java 八大排序算法 冒泡排序 快速排序 堆排序 归并排序 等...

    八大排序算法 一.直接插入 1.基本思路 在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的.如此反复循环 ...

  8. 图解八大排序算法——我见过的最详细的讲解(转)

    一.分类 1.内部排序和外部排序 内部排序:待排序记录存放在计算机随机存储器中(说简单点,就是内存)进行的排序过程. 外部排序:待排序记录的数量很大,以致于内存不能一次容纳全部记录,所以在排序过程中需 ...

  9. 八大排序算法的 Python 实现

    八大排序算法的 Python 实现 本文用Python实现了插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个数据插入 ...

最新文章

  1. 谱聚类(Spectral clustering)(2):NCut
  2. EditText中的几个常用属性
  3. pycharm python脚本自动头文件注释
  4. redis和memcached的区别(总结)
  5. 数据采集与网站统计实现全过程
  6. Linux mount 修改文件系统的读写属性
  7. ccf报数游戏java_ccf 201712 02 (游戏)
  8. 安装使用 superset
  9. python 吃cpu 显卡 内存_浅析 Pycharm 内存、cpu 占用率
  10. 记录第一次用阿里云(Windows主机)部署SSM项目(Spring+SpringMVC+Mybatis)
  11. android 广播自启动,关于BOOT_COMPLETED广播-自启动
  12. 杭州拒绝车辆“带病”上路 OBD在线接入实现排放动态监管
  13. linux 程序结构,Objective-C 基本的程序结构
  14. Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection brok
  15. 10以内的分解与组成怎么教_如何教宝宝熟记10以内分解?
  16. 9100cdn打印有色差_uv打印机出现色差的解决方法
  17. Huffman二进制编码以及文本的压缩与解压
  18. 报错解决:selenium.common.exceptions.WebDriverException: Message: An unknown server-side error
  19. 被刷了N次才获得的offer,却因“时间不合”泡汤了!?
  20. 推荐一个批量群控N台远程桌面的效率工具-黑马远程桌面5.12版

热门文章

  1. linux双击运行jar包,linux下发布JAR包 并运行
  2. 准静态、静态、动态(动力学分析)
  3. 用Mapviz显示卫星地图轨迹
  4. 送书 | 哈佛大学单细胞课程:笔记汇总前篇
  5. 神经系统分类和组成图表,神经系统的组成概念图
  6. Facebook广告投放的正确姿势:玩转目标定位
  7. pwn入门系列-ret2libc2
  8. ffmpeg中AVPacket与AVFrame中数据的传递与释放
  9. 分享几款好用的软件,建议低调收藏
  10. 关注木马是如何免杀的