稳定排序与不稳定排序方法

2023-11-08

这几天笔试了好几次了,连续碰到一个关于常见排序算法稳定性判别的问题,往往还是多选,对于我以及和我一样拿不准的同学可不是一个能轻易下结论的题目,当然如果你笔试之前已经记住了数据结构书上哪些是稳定的,哪些不是稳定的,做起来应该可以轻松搞定。本文是针对老是记不住这个或者想真正明白到底为什么是稳定或者不稳定的人准备的。

首先,排序算法的稳定性大家应该都知道,通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。在简单形式化一下,如果Ai = Aj,Ai原来在位置前,排序后Ai还是要在Aj位置前。

其次,说一下稳定性的好处。排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。基数排序就是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。另外,如果排序算法稳定,对基于比较的排序算法而言,元素交换的次数可能会少一些(个人感觉,没有证实)。

回到主题,现在分析一下常见的排序算法的稳定性,每个都给出简单的理由。

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

综上,得出结论: 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法





不稳定的排序算法有:快、希、选、堆。(记忆:找到工作就可以“快些选一堆”美女来玩了(并不能))



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

稳定排序与不稳定排序方法 的相关文章

  • Vuforia⭐二、动态修改识别目标和3D物体

    目录 本节的目标 动态识别的实现方法 本节的目标 本章目标为不设置ImageTarget Unity完成动态识别识别图 动态识别的实现方法 1 Vuforia官网上传识别目标 下载unitypackage并导入Unity 2 导入Vufor
  • Spring 事务详解

    目录 一 概述 二 事务的特性 ACID 三 Spring 的事务管理 3 1 编程式事务管理 3 2 编程式事务管理 四 Spring 事务管理接口及其定义的属性 4 1 PlatformTransactionManager 事务管理接口

随机推荐

  • c++入门笔记-list链表

    list基本概念 功能 将数据进行链式存储 链表是一种物理存储单元上非连续的存储结构 数据元素的逻辑顺序是通过链表中的指针链接实现 链表的组成 由一系列结点组成 结点的组成 一个是存储元素的数据域 另一个是存储下一个结点地址的指针域 stl
  • SQL练习题之求平均分低于80分的班级学生各科成绩并合计学生总分

    是对是错也好 不必说了 是怨是爱也好 不须揭晓 何事更重要 比两心的需要 柔情蜜意怎么可缺少 说不出再见 谭咏麟 文章目录 前言 一 练习题题目 二 创建测试数据 一 创建测试表 二 插入测试数据 三 思路 四 解答 一 详细代码 二 结果
  • windows Caffe 动态库 静态库 编译教程

    博主所在的教研室要使用Caffe实现机械臂的控制环节中的预测部分 其中涉及到了Caffe的编译以及LSTM层的添加到最终的caffe的动态库和静态库的编译及使用 整个过程一言难尽 特写此博客纪念 首先是caffe的编译 网上的教程都是大同小
  • linux dl_open hook

    http www myhack58 com Article html 3 68 2012 35408 htm 一步一步走进Linux HOOK API 八 分类 Linux 2012 07 23 21 30 385人阅读 评论 1 收藏 举
  • 受挫了,看没有注释的代码(几年前帖子,私密变公开后时间就变了)

    公司代码是DX9写的 确实写的不错 接口文档也是 但是没有注释 350页文档 这周刚看 又安排新任务 卧槽 请教问题也说不清楚 b s模式 调试起来 com组件写的
  • keras搭建神经网络

    Keras是一个神经网络开发的高级API 用Python编写 底层调用神经网络开发库TensorFlow CNTK或Theano Keras的目标是简化神经网络应用开发过程 快速实现想法 Keras 后端 Keras 是一个模型级库 为开发
  • 伸缩自如的ElasticSearch——数据库索引原理

    文章目录 引言 B B Tree 聚集索引 非聚集索引 覆盖索引 引言 使用索引很简单 只要能写创建表的语句 就肯定能写创建索引的语句 要知道这个世界上是不存在不会创建表的服务器端程序员的 然而 会使用索引是一回事 而深入理解索引原理又能恰
  • 千字文 uni-app的基础、uni-app入门 点击后屏幕底部出现弹框, 页头导航按钮和文字怎么写, 元素头部标记的用法​​, 底部导航栏icon图标, 收取短信的输入框​, 页面跳转信息存储不变

    为什么说是基础知识点呢 因为深点儿的东西我不会 虽然说小程序这类的也接触过 但是 皮毛 是个类似于携程的民宿App 就是租房用的 小程序俺不擅长 一边学一边写 免不了速度慢 先说说这几天遇到的点吧 虽然都是简单的问题 但是 对新手应该很友好
  • 低版本的openwrt添加openwrt19的支持的python3软件包

    openwrt的扩展软件包放在feeds目录下 python相关的包在feeds packages lang python下 原本openwrt18是不支持python pyserial的 只要从openwrt19中的feeds packa
  • Cache对运营商的意义,对小运营商的意思更大

    转自 http cndefu blog 163 com blog static 59393188201081811111248 Cache对运营商的意义 摘要 各互联网运营商与Chinanet等互联 每月付大量的带宽租用费 在互联互通出口
  • v-text和v-html的区别

    v text和 表达式渲染数据 不解析标签 v html不仅可以渲染数据 而且可以解析标签
  • SQLite Expert (Andorid Sqlite 可视化工具)中文乱码问题解决

    点击菜单栏Tools 继续点击Options 点击第二个General 将Encoding改为 Unicode utf 8 utf 16
  • Java课题笔记~ MyBatis缓存

    为了减少重复查询给数据库带来的压力 MyBatis提供了缓存机制 这种机制能够缓存查询的结果 避免重复的查询 MyBatis提供了两种缓存方式 一种为针对于SqlSession的缓存 默认开启 另一种为针对于全局的缓存 手动开启 一级缓存存
  • python case when用法_oracle菜鸟学习之 select case when的使用

    toc oracle菜鸟学习之 select case when的使用 格式语法 case when 条件1 then action1 when 条件2 then action2 when 条件3 then action3 when 条件N
  • Hexo 在subtile和description中实现换行

    如下所示 用双引号括起来 同时实现 br 即可达到换行目的 Site title LEO S NOTE 标题 subtitle 心有猛虎 细嗅蔷薇 副标题 description Stay Hungry br Stay Foolish 简介
  • Quartus Primer 17.0 下载和安装

    在对FPGA进行开发的过程中 一款合适的IDE是少不了的 Intel Altera 的FPGA使用Quartus Primer 软件进行开发 记录一下Quartus II 17 0下载安装的过程 一 下载 1 在Intel的官网 https
  • 第15章Stata时间序列分析

    目录 15 1时间序列的基本操作 案例延伸 延伸1 清除数据的时间序列格式 延伸2 关于数据处理的一般说明 延伸3 关于时间序列运算的有关说明 15 2单位根检验 1 ADF检验 2 PP检验 案例延伸 15 3协整检验 1 EF ADF检
  • 数据库关系表 ---- Relational table

    数据库关系表 Relational table 什么是关系 relation 关系 relation 的基本属性 约束 Constraints Integrity Constraints 完整性约束 Referential Integrit
  • Zookeeper分布式锁的实现

    众所周知 多个服务间的调用 产生多个JVM问题 当我们使用传统的锁的时候就会出现问题 因为跨JVM中无法可见到同一把锁 这个时候分布式锁就应运而生 例如就出现了Redis分布式锁 基于setnx的方式去实现 当然我们也可以通过zookeep
  • 稳定排序与不稳定排序方法

    这几天笔试了好几次了 连续碰到一个关于常见排序算法稳定性判别的问题 往往还是多选 对于我以及和我一样拿不准的同学可不是一个能轻易下结论的题目 当然如果你笔试之前已经记住了数据结构书上哪些是稳定的 哪些不是稳定的 做起来应该可以轻松搞定 本文