数据结构学习笔记——基数排序 | 排序算法总结

一、基数排序排序思想

基数排序与前面的排序算法不一样,它不基于比较和移动元素来进行排序,而是基于多关键字排序的思想,将一个逻辑关键字分为多个关键字,它是基于关键字各位的大小进行排序的。基数排序有两种实现方式:最高位优先法最低位优先法,分别是按关键字高次位排序和低次位排序。

例如,下面通过最低位优先法,对给定的关键字序列{110,119,007,911,114,120,122}进行排序:

1、该序列的链式结构如下:
在这里插入图片描述
2、首先按照关键字的个位数字大小进行第一趟基数排序:
在这里插入图片描述
3、根据第一趟的顺序,按照关键字的十位数字大小进行第二趟基数排序:
在这里插入图片描述
4、根据第二趟的顺序,按照关键字的百位数字大小进行第三趟基数排序:
在这里插入图片描述
即,通过最低位优先法,得到排好的序列为{007,110,114,119,120,122,911}。

二、基数排序算法分析

分析
(1)基数排序适用于:

1、数据元素的关键字可以很容易地进行拆分成d组,且d较小;
2、每组关键字的取值范围不大,即r较小;
3、数据元素个数n较大。

(2)空间复杂度:每一趟基数排序需要辅助空间r个队列,每趟排序后会重复使用这些队列,基数排序的空间复杂度为O( r )。
(3)时间复杂度:其时间复杂度与初始序列无关,基数排序需进行d趟分配和收集操作,一趟分配需要O(n)数量级,一趟收集需要O( r )数量级,即总排序的时间复杂度为O(d(n+r))。
(4)稳定性:基数排序是一种稳定的排序算法。
(5)适用性:基数排序适用于链式存储。
(6)排序方式:基数排序与前面的归并排序一样,也是是一种外部排序(Out-place)。

三、排序算法总结

(一)分类

常用排序算法如下,其中归并排序和基数排序是外部排序:

排序算法
插入排序
直接插入排序
折半插入排序
希尔排序
选择排序
简单选择排序
堆排序
交换排序
冒泡排序
快速排序
归并排序
基数排序

(二)比较

排序算法 空间复杂度 平均时间复杂度 最好时间复杂度 最坏时间复杂度 排序方式 稳定性 适用性
直接插入排序 O(1) O(n2) O(n) O(n2) 内部排序(In-place) 顺序存储和链式存储
折半插入排序 O(1) O(n2) O(nlog2n) O(n2) 内部排序(In-place) 顺序存储
希尔排序 O(1) 依赖于增量序列 依赖于增量序列 依赖于增量序列 内部排序(In-place) × 顺序存储
冒泡排序 O(1) O(n2) O(n) O(n2) 内部排序(In-place) 顺序存储和链式存储
简单选择排序 O(1) O(n2) O(n2) O(n2) 内部排序(In-place) × 顺序存储和链式存储

续表:

排序算法 空间复杂度 平均时间复杂度 最好时间复杂度 最坏时间复杂度 排序方式 稳定性 适用性
快速排序 最好为O(log2n);最坏为O(n);平均情况下,为O(log2n) O(nlog2n) O(nlog2n) O(n2) 内部排序(In-place) × 顺序存储
堆排序 O(1) O(nlog2n) O(nlog2n) O(nlog2n) 内部排序(In-place) × 顺序存储
归并排序 O(n) O(nlog2n) O(nlog2n) O(nlog2n) 外部排序(Out-place) 顺序存储和链式存储
基数排序 O( r ) O(d(n+r)) O(d(n+r)) O(d(n+r))) 外部排序(Out-place) 链式存储

(三)详细分析

1、稳定性
(1)直接/折半插入排序、冒泡排序、归并排序和基数排序是稳定的排序算法,其中平均时间复杂度为O(nlog2n)的稳定排序只有归并排序。
(2)简单选择排序、希尔排序、快速排序和堆排序是不稳定的排序算法。
2、时间复杂度和空间复杂度
(1)直接/折半插入排序、简单选择排序、冒泡排序是简单型的排序算法,实现过程较简单,时间复杂度均为O(n2),但在最好情况下折半插入排序可以达到O(nlog2n),直接插入排序和冒泡排序可以达到O(n),由于简单选择排序中元素的比较次数与序列的初始状态无关,其时间复杂度始终为O(n2);另外,这四种排序的空间复杂度均为O(1)。

排序算法 空间复杂度 平均时间复杂度 最好时间复杂度 最坏时间复杂度
直接插入排序 O(1) O(n2) O(n) O(n2)
折半插入排序 O(1) O(n2) O(nlog2n) O(n2)
冒泡排序 O(1) O(n2) O(n) O(n2)
简单选择排序 O(1) O(n2) O(n2) O(n2)

(2)希尔排序也称为缩小增量排序,它属于插入类算法,是插入排序的拓展,在时间复杂度上有较大的改进,对较大规模的排序可以达到很高的效率,但无法得出较精确的渐进时间;希尔排序的空间复杂度也为O(1)。

排序算法 空间复杂度 平均时间复杂度 最好时间复杂度 最坏时间复杂度
希尔排序 O(1) 依赖于增量序列 依赖于增量序列 依赖于增量序列

(3)堆排序、快速排序和归并排序是改进型的排序算法,其时间复杂度均为O(nlog2n),堆排序是由于通过使用堆这种数据结构,快速排序和归并排序都采用分治的思想,但当快速排序的初始序列为有序或逆序时,为最坏情况,时间复杂度会达到O(n2),而归并排序中,比较次数与初始序列无关,即分割子序列与初始序列是无关的,后两者的时间复杂度与堆排序一样都是O(nlog2n) ;另外,空间复杂度分别为O(1) 、O(log2n)和O(n) ,其中堆排序只需借助常数个辅助空间,快速排序中需借助栈来进行递归,其空间复杂度与递归层数(栈的深度)有关,最好和平均情况下均为O(log2n),而最坏情况下为O(n)。归并排序中也用到了递归工作栈,递归工作栈的空间复杂度为O(log2n),由于另外还需用到辅助数组,其空间复杂度为O(n),所以该排序算法的空间复杂度为O(n)。

排序算法 空间复杂度 平均时间复杂度 最好时间复杂度 最坏时间复杂度
快速排序 最好为O(log2n);最坏为O(n);平均情况下,为O(log2n) O(nlog2n) O(nlog2n) O(n2)
堆排序 O(1) O(nlog2n) O(nlog2n) O(nlog2n)
归并排序 O(n) O(nlog2n) O(nlog2n) O(nlog2n)

3、根据规模大小选择排序算法
(1)一般来说,对于要排序元素较多的序列,可以选用时间复杂度为O(nlog2n)的堆排序、快速排序和归并排序算法,其中快速排序是目前基于比较的内部排序中最好的排序算法,但它要求初始序列随机分布这样才会使快速排序的平均时间最短。堆排序的空间复杂度小于快速排序,它不会出现快速排序中的最坏情况。前两种排序算法都是不稳定的,因此若要选择时间复杂度为O(nlog2n)且稳定的排序算法,可以选择归并排序,通过将该算法与直接插入排序结合起来,即通过直接插入排序求得有序子序列后,再合并,这样的归并算法依旧是稳定的。
(2)若要排序元素很大,记录的元素位数较少时,应选用基数排序。
(3)而对于排序元素较少的序列,可以选用时间复杂度为O(n2)的直接/折半插入排序、冒泡排序、简单选择排序算法,由于简单选择排序的移动次数比直接插入排序少,所以当元素信息量较大时,应选用简单选择排序。
4、平均比较次数
(1)在插入排序、希尔排序、选择排序、快速排序、堆排序、归并排序和基数排序中,平均比较次数最少的排序是快速排序。
(2)直接插入排序和简单选择排序对比:通常情况下,直接插入排序每趟插入都需向后一次挪位,而简单选择排序只需找到最小/最大元素与其交换位置即可,它的移动次数较少。

考虑在较极端情况下,对于有序数组,直接插入排序的比较次数为n-1;而简单选择排序的比较次数始终为n(n-1)/2。

5、排序趟数
直接插入排序、简单选择排序和基数排序的排序趟数与初始序列无关
(1)直接插入排序由于每趟都插入一个元素至已排好的子序列,所以排序趟数固定为n-1次;
(2)简单选择排序中,每趟排序都选出一个最小/最大的元素,所以排序趟数也固定为n-1次;
(3)基数排序需进行d趟分配和收集操作。
6、每趟排序确定的元素
每一趟排序算法的进行都能确定一个元素处于其最终位置的排序算法有以下:

①冒泡排序
②简单选择排序
③堆排序
④快速排序
前三者能形成整体有序的子序列,而后者快速排序只确定枢轴元素的最终位置
(第n趟快速排序完成时,会有n个以上的元素处于其最终结果位置上,
即它们两边的元素分别比它大或小)。

7、顺序存储和链式存储
插入排序、选择排序和冒泡排序采用顺序存储的时间复杂度为O(n2),若采用链式存储依然是O(n2);而希尔排序和堆排序都利用了顺序存储的随机访问特性,它们都不支持链式存储,若采用则会增加时间复杂度,降低效率。

猜你喜欢

转载自blog.csdn.net/qq_43085848/article/details/127833634