各种内部排序算法的比较及应用(插入排序、交换排序、选择排序、归并排序、基数排序)

目录

内部排序

前言

1.内部排序算法的比较

1.1各种排序算法的特点、比较和适用场景

1.2排序算法的稳定性判断及改进 

1.3更适合采用顺序存储的排序算法

1.4根据排序的中间过程判断所采用的排序算法

1.5各种排序算法的性质

2.内部排序算法的应用

2.1选取排序算法时需要考虑的因素

2.2排序算法小结

 3.内部排序各种算法性能分析

3.1直接插入排序

3.2折半插入排序

3.3希尔排序

3.4冒泡排序

3.5快速排序

3.6简单选择排序

3.7堆排序

3.8归并排序

3.9基数排序

3.10计数排序 


内部排序

前言

这篇文章总结了所有内部排序的适用场景,性质特点,以及空间和时间复杂度的考量;

前半部分是对内部排序的总结,后半部分是对所有内部排序的具体性能分析;

1.内部排序算法的比较

  • 前面讨论的排序算法很多,对各种排序算法的比较是考研常考的内容。
  • 一般基于五个因素进行对比:时间复杂度、空间复杂度、稳定性、适用性和过程特征

1.1各种排序算法的特点、比较和适用场景

从时间复杂度看


简单选择排序、直接插入排序和冒泡排序平均情况下的时间复杂度都为O(n²),且实现过程也较为简单,但直接插入排序和冒泡排序最好情况下的时间复杂度可以达到O(n),而简单选择排序则与序列的初始状态无关。


希尔排序作为插入排序的拓展,对较大规模的数据都可以达到很高的效率,但目前未得出其精确的渐近时间。


堆排序利用了一种称为堆的数据结构,可以在线性时间内完成建堆,且在 O(nlog₂n)内完成排序过程。


快速排序基于分治的思想,虽然最坏情况下的时间复杂度会达到 O(n²),但快速排序的平均性能可以达到 O(nlog₂n),在实际应用中常常优于其他排序算法。


归并排序同样基于分治的思想,但由于其分割子序列与初始序列的排列无关,因此它的最好、最坏和平均时间复杂度均为 O(nlog₂n)。

从空间复杂度看


简单选择排序、插入排序、冒泡排序、希尔排序和堆排序都仅需借助常数个辅助空间。


快速排序需要借助一个递归工作栈,平均大小为 O(log₂n),当然在最坏情况下可能会增长到 O(n)。


二路归并排序在合并操作中需要借助较多的辅助空间用于元素复制,大小为 O(n),虽然有方法能克服这个缺点,但其代价是算法会很复杂而且时间复杂度会增加。

1.2排序算法的稳定性判断及改进 

从稳定性看:


插入排序、冒泡排序、归并排序和基数排序是稳定的排序算法,


简单选择排序、快速排序、希尔排序和堆排序都是不稳定的排序算法。


平均时间复杂度为 O(nlog₂n)的稳定排序算法只有归并排序,对于不稳定的排序算法,只需举出一个不稳定的实例即可。


对于排序算法的稳定性,读者应能从算法本身的原理上去理解,而不应拘泥于死记硬背。

1.3更适合采用顺序存储的排序算法

从适用性看:


折半插入排序、希尔排序、快速排序和堆排序适用于顺序存储。


直接插入排序、冒泡排序、简单选择排序、归并排序和基数排序既适用于顺序存储,又适用于链式存储。

1.4根据排序的中间过程判断所采用的排序算法

从过程特征看:


采用不同的排序算法,在一趟或几趟处理后的排序结果通常是不同的,考研题中经常出现给出一个待排序的初始序列和已部分排序的序列,问其采用何种排序算法。


这就要对各类排序算法的过程特征十分熟悉,如冒泡排序、简单选择排序和堆排序在每趟处理后都能产生当前的最大值或最小值,


快速排序一趟处理至少能确定一个元素的最终位置等。


下表列出了各种排序算法的时空复杂度和稳定性情况,其中空间复杂度仅列举了平均情况的复杂度,因为希尔排序的时间复杂度依赖于增量函数,所以无法准确给出其时间复杂度。

1.5各种排序算法的性质

算法种类时间复杂度空间复杂度是否稳定
最好情况平均情况最坏情况

直接插入排序

O(n)O(n²)O(n²)O(1)
冒泡排序O(n)O(n²)O(n²)O(1)
简单选择排序O(n²)O(n²)O(n²)O(1)
希尔排序O(1)
快速排序O(nlog₂n)O(nlog₂n)O(n²)O(log₂n)
堆排序O(nlog₂n)O(nlog₂n)O(nlog₂n)O(1)
二路归并排序O(nlog₂n)O(nlog₂n)O(nlog₂n)O(n)
基数排序O(d(n+r))O(d(n+r))O(d(n+r))O(r)

2.内部排序算法的应用

2.1选取排序算法时需要考虑的因素

  1. 待排序的元素个数 n。
  2. 待排序的元素的初始状态。
  3. 关键字的结构及其分布情况。
  4. 稳定性的要求。
  5. 存储结构及辅助空间的大小限制等。

2.2排序算法小结

1)

  • 若 n较小,可采用直接插入排序或简单选择排序。
  • 由于直接插入排序所需的记录移动次数较简单选择排序的多,因此当记录本身信息量较大时,用简单选择排序较好。

2)

  • 若n较大,应采用时间复杂度为 O(nlog₂n)的排序算法:快速排序、堆排序或归并排序。
  • 当待排序的关键字随机分布时,快速排序被认为是目前基于比较的内部排序算法中最好的算法。
  • 堆排序所需的辅助空间少于快速排序,且不会出现快速排序可能的最坏情况,这两种排序都是不稳定的。
  • 若要求稳定且时间复杂度为 O(nlog₂n),可选用归并排序。

3)

  • 若文件的初始状态已按关键字基本有序,则选用直接插入或冒泡排序为宜。


4)

  • 在基于比较的排序算法中,每次比较两个关键字的大小之后,仅出现两种可能的转移,因此可以用一棵二叉树来描述比较判定过程,
  • 由此可以证明:当文件的n个关键字随机分布时,任何借助于“比较”的排序算法,至少需要 O(nlog₂n)的时间。

5)

  • 若n很大,记录的关键字位数较少且可以分解时,采用基数排序较好。

6)

  • 当记录本身信息量较大时,为避免耗费大量时间移动记录,可用链表作为存储结构。

 3.内部排序各种算法性能分析

3.1直接插入排序

直接插入排序算法的性能分析如下:

空间效率:仅使用了常数个辅助单元,因而空间复杂度为O(1)


时间效率:在排序过程中,向有序子表中逐个地插入元素的操作进行了n-1趟,

  • 每趟操作都分为比较关键字和移动元素,而比较次数和移动次数取决于待排序表的初始状态。
  • 在最好情况下,表中元素已经有序,此时每插入一个元素,都只需比较一次而不用移动元素,因而时间复杂度为 O(n)。
  • 在最坏情况下,表中元素顺序刚好与排序结果中的元素顺序相反(逆序),总的比较次数达到最大,总的移动次数也达到最大,总的时间复杂度为O(n²)。
  • 平均情况下,考虑待排序表中元素是随机的,此时可以取上述最好与最坏情况的平均值作为平均情况下的时间复杂度,总的比较次数与总的移动次数均约为n²/4。
  • 因此,直接插入排序算法的时间复杂度为 O(n²)

稳定性:因为每次插入元素时总是从后往前先比较再移动,所以不会出现相同元素相对位置发生变化的情况,即直接插入排序是一个稳定的排序算法。


适用性直接插入排序适用于顺序存储和链式存储的线性表,采用链式存储时无须移动元素

3.2折半插入排序

折半插入排序算法的性能分析如下:

空间效率:在排序过程中只需要额外使用常数级别的额外空间,不随待排序数组的大小而变化,所以空间复杂度为O(1)。


时间效率:折半插入排序仅减少了比较元素的次数,该比较次数与待排序表的初始状态无关,仅取决于表中的元素个数n;

而元素的移动次数并未改变它依赖于待排序表的初始状态。

因此,折半插入排序的时间复杂度仍为 O(n²),但对于数据量不很大的排序表,折半插入排序往往能表现出很好的性能。


稳定性:折半插入排序是一种稳定的排序算法。


适用性:折半插入排序仅适用于顺序存储的线性表

3.3希尔排序

希尔排序算法的性能分析如下:

空间效率:仅使用了常数个辅助单元,因而空间复杂度为O(1)


时间效率:因为希尔排序的时间复杂度依赖于增量序列的函数,这涉及数学上尚未解决的难题,所以其时间复杂度分析比较困难。

  • 当n在某个特定范围时,希尔排序的时间复杂度约为O(n^{1.3})
  • 在最坏情况下希尔排序的时间复杂度为O(n²)。

稳定性:当相同关键字的记录被划分到不同的子表时,可能会改变它们之间的相对次序,

因此希尔排序是一种不稳定的排序算法。例如,图82中49与49的相对次序已发生了变化。


适用性:希尔排序仅适用于顺序存储的线性表。

3.4冒泡排序

冒泡排序的性能分析如下:

空间效率:仅使用了常数个辅助单元,因而空间复杂度为O(1)


时间效率:当初始序列有序时,显然第一趟冒泡后 flag 依然为 false(本趟没有元素交换),从而直接跳出循环,比较次数为n-1,移动次数为0,

  • 从而最好情况下的时间复杂度为 O(n)
  • 当初始序列为逆序时,需要进行n-1趟排序,第 i 趟排序要进行n-i次关键字的比较,而且每次比较后都必须移动元素3次来交换元素位置。
  • 这种情况下, 
  • 比较次数=\sum_{i=1}^{n-1}(n-i)=\frac{n(n-1)}{2}
  • 移动次数=\sum_{i=1}^{n-1}3(n-i)=\frac{3n(n-1)}{2}
  • 从而,最坏情况下的时间复杂度为 O(n²),平均时间复杂度为 O(n²)

稳定性:由于 i>j 且 A[i]=A[j] 时,不会发生交换,因此冒泡排序是一种稳定的排序算法


适用性:冒泡排序适用于顺序存储和链式存储的线性表

3.5快速排序

快速排序算法的性能分析如下:

  • 空间效率:由于快速排序是递归的,因此需要借助一个递归工作栈来保存每层递归调用的必要信息,其容量与递归调用的最大层数一致。
  • 最好情况下为 O(log₂n);
  • 最坏情况下,要进行n-1次递归调用,因此栈的深度为 O(n);
  • 平均情况下,栈的深度为 O(log₂n)。

  • 时间效率快速排序的运行时间与划分是否对称有关,快速排序的最坏情况发生在两个区域分别包含n-1个元素和0个元素时,这种最大限度的不对称性若发生在每层递归上,即对应于初始排序表基本有序或基本逆序时,就得到最坏情况下的时间复杂度为 O(n²)。

  • 有很多方法可以提高算法的效率:一种方法是尽量选取一个可以将数据中分(对称平分)的枢轴元素,如从序列的头尾及中间选取三个元素,再取这三个元素的中间值作为最终的枢轴元素;或者随机地从当前表中选取枢轴元素,这样做可使得最坏情况在实际排序中几乎不会发生。

  • 在最理想的状态下,即 Partition()能做到最平衡的划分,得到的两个子问题的大小都不可能大于 n/2,在这种情况下,快速排序的运行速度将大大提升,此时,时间复杂度为 O(nlog₂n)。
  • 好在快速排序平均情况下的运行时间与其最佳情况下的运行时间很接近,而不是接近其最坏情况下的运行时间。
  • 快速排序是所有内部排序算法中平均性能最优的排序算法。

  • 稳定性:在划分算法中,若右端区间有两个关键字相同,且均小于基准值的记录,则在交换到左端区间后,它们的相对位置会发生变化,即快速排序是一种不稳定的排序算法
  • 例如,表L=(3,2,2),经过一趟排序后L={2,2,3},最终排序序列也是L={2,2,3},显然,2与2的相对次序已发生了变化。

  • 适用性:快速排序仅适用于顺序存储的线性表

3.6简单选择排序

简单选择排序算法的性能分析如下:

空间效率:仅使用常数个辅助单元,所以空间效率为O(1)


时间效率:从上述伪码中不难看出,

  • 在简单选择排序过程中,元素移动的操作次数很少,不会超过 3(n-1)次,最好的情况是移动0次,此时对应的表已经有序;
  • 但元素间比较的次数与序列的初始状态无关,始终是 n(n-1)/2 次,因此时间复杂度始终是 O(n²)

稳定性

  • 在第 i 趟找到最小元素后,和第 i 个元素交换,可能会导致第 i 个元素与含有相同关键字的元素的相对位置发生改变。
  • 例如,表 L={2,2,1},经过一趟排序后 L={1,2,2),最终排序序列也是L={1,2,2},显然,2与2的相对次序已发生变化。
  • 因此,简单选择排序是一种不稳定的排序算法

适用性:简单选择排序适用于顺序存储和链式存储的线性表,以及关键字较少的情况

3.7堆排序

堆排序算法的性能分析如下:

空间效率:仅使用了常数个辅助单元,所以空间复杂度为O(1)


时间效率:建堆时间为 O(n),之后有n-1次向下调整操作,每次调整的时间复杂度为 O(h),

所以在最好、最坏和平均情况下,堆排序的时间复杂度为O(nlog₂n)


稳定性:进行筛选时,有可能把后面相同关键字的元素调整到前面,所以堆排序算法是一种不稳定的排序算法

  • 例如,表L={1,2,2),构造初始堆时可能将2交换到堆顶,此时L={2,1,2},最终排序序列为 L={1,2,2},显然,2与2的相对次序已发生变化。

适用性:堆排序仅适用于顺序存储的线性表

3.8归并排序

二路归并排序算法的性能分析如下:

空间效率:Merge()操作中,辅助空间刚好为n个单元,因此算法的空间复杂度为O(n)。


时间效率:每趟归并的时间复杂度为 O(n),共需进行\left \lceil log_{2}n \right \rceil趟归并,因此算法的时间复杂度为O(nlog_{2}n)


稳定性:由于 Merge()操作不会改变相同关键字记录的相对次序,因此二路归并排序算法是一种稳定的排序算法


适用性:归并排序适用于顺序存储和链式存储的线性表

3.9基数排序

基数排序算法的性能分析如下。

空间效率:一趟排序需要的辅助存储空间为r (r个队列:r个队头指针和r个队尾指针),但以后的排序中会重复使用这些队列,所以基数排序的空间复杂度为O(r)


时间效率

  • 基数排序需要进行 d趟“分配”和”收集”操作。
  • 一趟分配需要遍历所有关键字,时间复杂度为 O(n);
  • 一趟收集需要合并r个队列,时间复杂度为 O(r)。
  • 因此基数排序的时间复杂度为 O(d(n+r)),它与序列的初始状态无关

稳定性:每一趟分配和收集都是从前往后进行的,不会交换相同关键字的相对位置,因此基数排序是一种稳定的排序算法


适用性:基数排序适用于顺序存储和链式存储的线性表。 

3.10计数排序 

计数排序算法的性能分析如下。

空间效率:计数排序是一种用空间换时间的做法。

  • 输出数组的长度为n;
  • 辅助的计数数组的长度为 k,空间复杂度为 O(n+k)。
  • 若不把输出数组视为辅助空间,则空间复杂度为 O(k)。

时间效率

  • 上述代码的第1个和第3个for 循环所花的时间为 O(k),
  • 第2个和第4个 for 循环所花的时间为 O(n),
  • 总时间复杂度为 O(n+ k)。
  • 因此,当 k=O(n) 时,计数排序的时间复杂度为O(n);
  • 但当 k>O(nlog₂n)时,其效率反而不如一些基于比较的排序(如快速排序、堆排序等)。

稳定性:上述代码的第4个 for 循环从后往前遍历输入数组,相同元素在输出数组中的相对位置不会改变,因此计数排序是一种稳定的排序算法


适用性:计数排序更适用于顺序存储的线性表。计数排序适用于序列中的元素是整数且元素范围(0~k-1)不能太大,否则会造成辅助空间的浪费。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/23239.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UE4_Ben_图形52_水下效果处理

学习笔记,不喜勿喷,欢迎指正,侵权立删!祝愿生活越来越好! 在这个后期处理的效果中,我们可以看到有很多不同的,这里有浓雾,波纹扭曲,镜头扭曲和边缘模糊,在第4…

pcb实验六-元件设计

目录 一,绘制28管脚PLCC封装ATF750C-10JC元件 二,绘制变压器原理图符号,并生成各种库文件输出报表 1,绘制变压器原理图 2,添加封装 3,输出报表文件 三,绘制音乐集成芯片及LCD元件 1&…

Apache漏洞复现:【CVE-2021-42013】【CVE_2021_41773】【CVE-2017-15715】

声明 严禁读者利用本文介绍知识点对网站进行非法操作 , 本文仅用于技术交流和学习 , 如果您利用文章中介绍的知识对他人造成损失 , 后果由您自行承担 , 如果您不能同意该约定 , 请您务必不要阅读该文章 , 感谢您的配合 ! 远程代码执行 CVE-2021-42013 描述 Apache HTTP Ser…

R语言数据探索和分析21-中国GDP及其影响因素多元线性回归分析

一、研究背景和意义 GDP 是宏观经济中最受关注的经济统计数字,目前我国国内生产总值年均增长率均明显高于同期美、日等发达经济体和巴 西、俄罗斯、南非、印度等其他金砖国家,成为世界经济增长的主力军,GDP 的增长对一个国家有着十分重要的意…

mysql中事务的简介

大家好。我们在日常开发过程中肯定都或多或少的用到过事务,而且在面试时,数据库的事务也是必问内容之一。今天我们就来说说mysql的事务。 为了方便我们下面内容的讲解,我们也先建立一个讲事务必用的表–account表,并在表中插入两…

基于centos7打包当前环境的系统为iso镜像文件

1. 准备工作 1.下载安装mondo 切换到root用户,进入yum下载库 # cd /etc/yum.repos.d # wget ftp://ftp.mondorescue.org/centos/7/x86_64/mondorescue.repo 打开文件mondorescue.repo,修改gpgcheck属性为0,指定mondorescue.repo安装 # 安…

【Python数据挖掘实战案例】机器学习LightGBM算法原理、特点、应用---基于鸢尾花iris数据集分类实战

一、引言 1、简要介绍数据挖掘的重要性和应用 在数字化时代,数据已经成为企业和社会决策的重要依据。数据挖掘作为一门交叉学科,结合了统计学、机器学习、数据库技术和可视化等多个领域的知识,旨在从海量数据中提取有价值的信息&#xff0c…

生命在于学习——Python人工智能原理(3.2)

三、深度学习 (二)人工神经网络 人工神经网络是模仿人类大脑神经系统工作原理所创建的数学模型,有并行的分布处理能力、高容错性和自我学习等特征。 1、感知器 感知器由Frank Roseblatt于1957年提出,是一种广泛使用的线性分类…

RPC框架原理(一)

RPC框架原理 网络和IO的关系,IO(input和output)面向的是谁?OSI 7层参考模型,TCP/IP协议为什么会出现一个会话层三次握手socket心跳keep alive四次挥手 网络IO(IO模型) IO框架底层 学习顺序&…

GaussDB技术解读——GaussDB架构介绍(一)

目录 1 GaussDB 关键架构目标 2 GaussDB分布式架构 2.1 GaussDB 分布式关键技术架构 3 数据计算路由层(Coordinator)关键技术方案 3.1 分布式优化器 3.2 分布式执行框架 GaussDB是华为自主创新研发的关系型数据库,基于华为在数据库领域…

api接口模块封装

1:前端封装接口 前端请求的统一封装也是为了方便前端项目的请求维护起来更加方便,将页面中的请求封装到js文件中,不同的页面需要用到相同的请求可以直接进行复用。 第一步创建一个api文件夹和js文件 第二步:在文件中导入axios&am…

为什么投资气膜网球馆是明智之选—轻空间

在现代体育产业快速发展的背景下,投资体育场馆成为许多投资者关注的焦点。其中,气膜网球馆以其独特的优势和广泛的市场需求,逐渐成为投资者的热门选择。那么,为什么投资气膜网球馆是一个明智之选呢? 1. 建设周期短&…

SpringBoot+Vue幼儿园管理系统(前后端分离)

技术栈 JavaSpringBootMavenMyBatisMySQLVueElement-UI 系统角色 教师用户管理员 功能截图

JAVA小案例-输出100-150中能被3整除的数,每5个换行

JAVA小案例-输出100-150中能被3整除的数,每5个换行 代码如下: public class Continue {/*** continue练习,输出100-150中能被3整除的数,每5个换行* param args*/public static void main(String[] args) {int count 0;//计数器…

【全开源】数据大屏系统源码(ThinkPHP+FastAdmin)

📈数据大屏系统:可视化数据的魅力舞台🖥 基于ThinkPHPFastAdmin开发的数据大屏,可视化义拖拽快速制作数据大屏/科技大屏, 内置30组件、获取实时数据、使用简单易上手,轻松实现图形数据统计等。​ 一、引言…

03--nginx架构实战

前言:这应该是nginx梳理的最后一章,写一些关于网站架构和网站上线的知识内容,主要是感觉到运维并不是单一方向的行业,这一章概念会有一些广泛,但是非常重要,都是这几年工作中遇到的情况,整理一下…

【设计模式】JAVA Design Patterns——Private Class Data(私有类数据设计模式)

🔍目的 私有类数据设计模式试图通过限制属性的可见性来减少属性的暴露。 通过将它们封装在单个Data对象中,可以减少类属性的数量。 🔍解释 真实世界例子 想象一下你在为家人做晚餐炖汤。你想阻止家庭成员在你烹饪时偷偷品尝菜品,否…

C#WPF数字大屏项目实战08--生产量/良品统计

1、区域划分 生产量/良品统计这部分位于第二列的第二行 2、livechart拆线图 定义折线图,如下: <lvc:CartesianChart> <lvc:CartesianChart.Series> <!--设置Series的类型为 Line 类型, 该类型提供了一些折线图的实现--> <lvc:LineSeries/>…

什么是Vector Database(向量数据库)?

什么是Vector Database(向量数据库)&#xff1f; 向量数据库是向量嵌入的有组织的集合&#xff0c;可以随时创建、读取、更新和删除。向量嵌入将文本或图像等数据块表示为数值。 文章目录 什么是Vector Database(向量数据库)&#xff1f;什么是嵌入模型(Embedding Model)&…

idea 常用插件推荐

文章目录 1、Lombok2、Convert YAML and Properties File3、Grep Console4、MyBatisX5、Free MyBatis Tool6、MyBatis Log EasyPlus &#xff08;SQL拼接&#xff09;7、MyBatisPlus8、Eclipse theme9、Eclipse Plus Theme10、Rainbow Brackets Lite - Free and OpenSource&…