一、常见排序方法分类
插入排序类
- 直接插入排序:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
- 希尔排序:是插入排序的一种改进版本,先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
选择排序类
- 简单选择排序:在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(或最大)元素,放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
- 堆排序:利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质,即子节点的键值或索引总是小于(或者大于)它的父节点。
交换排序类
- 冒泡排序:重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复进行的,直到没有再需要交换的元素为止。
- 快速排序:选择一个基准元素,通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
归并排序
原理:采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。基数排序
原理:一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。计数排序
原理:不是基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。
二、综合比较
时间复杂度
- 冒泡排序、简单选择排序、直接插入排序:最坏情况下时间复杂度为O(n^2),适用于数据量较小的情况。
- 希尔排序:时间复杂度依赖于增量序列的选择,但通常优于O(n^2)。
- 快速排序:平均时间复杂度为O(n log n),但在最坏情况下(如数组已经有序)时间复杂度为O(n^2)。通过优化,如随机选择基准元素,可以降低最坏情况的发生概率。
- 堆排序、归并排序:时间复杂度稳定为O(n log n),适用于数据量较大的情况。
- 基数排序、计数排序:时间复杂度为O(n+k),其中k与数据的具体分布有关。基数排序适用于整数排序且数据位数较多的情况;计数排序适用于数据范围较小且为整数的情况。
空间复杂度
- 冒泡排序、简单选择排序、直接插入排序:空间复杂度为O(1),即只需要常数级别的额外空间。
- 希尔排序:空间复杂度为O(1),但实现时可能需要额外的数组来存储增量序列。
- 快速排序:空间复杂度为O(log n),主要用于递归调用栈的空间开销。通过迭代实现可以降低空间复杂度,但可能增加代码复杂度。
- 堆排序:空间复杂度为O(1),但需要额外的空间来维护堆结构(通常在原数组上进行操作)。
- 归并排序:空间复杂度为O(n),需要额外的数组来存储合并后的结果。通过原地归并可以减少空间开销,但实现较为复杂。
- 基数排序、计数排序:空间复杂度为O(n+k),其中k与数据的具体分布有关。需要额外的数组来存储桶或计数结果。
稳定性
- 冒泡排序、直接插入排序、归并排序:稳定排序,即相等元素的相对顺序在排序前后保持不变。
- 简单选择排序、快速排序、堆排序:不稳定排序,即相等元素的相对顺序可能会发生变化。
- 希尔排序:不稳定排序,因为分组插入排序可能破坏相等元素的相对顺序。
- 基数排序:稳定排序,因为每次分配和收集操作都保持相等元素的相对顺序。
- 计数排序:稳定排序,因为计数和排序过程都保持相等元素的相对顺序。
适用场景
- 数据量较小且对稳定性有要求时,可以选择冒泡排序、直接插入排序或归并排序。
- 数据量较大且对空间复杂度有要求时,可以选择堆排序或快速排序(通过优化降低最坏情况的发生概率)。
- 数据为整数且位数较多时,可以选择基数排序。
- 数据范围较小且为整数时,可以选择计数排序。
结语
清醒时做事,糊涂时读书
大怒时睡觉,独处时思考
!!!