排序,是算法中的经常需要用到的一些操作;所以,对于一些常见的排序算法,对其做一下总结还是很有必要的。
排序算法 | 平均时间复杂度 | 最坏时间复杂度 | 稳定性 |
---|---|---|---|
冒泡排序 | O(n²) | O(n²) | 稳定 |
选择排序 | O(n²) | O(n²) | 不稳定 |
插入排序 | O(n²) | O(n²) | 稳定 |
希尔排序 | O(n(logn)) | O(nlog²n) | 不稳定 |
归并排序 | O(n(logn)) | O(n(logn)) | 稳定 |
快速排序 | O(n(logn)) | O(n²) | 不稳定 |
鸽巢排序 | O(N+n) | O(N+n) | 稳定 |
堆排序 | O(n(logn)) | O(n(logn)) | 不稳定 |
(1)对于鸽巢排序,n是数组长度,N是最大值减最小值。
(2)稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,则称这种排序算法是稳定的;否则称为不稳定的。例如,若按身高对学生进行排序,当有两人身高一样时,稳定排序不会打乱两人本来的相对位置,而不稳定的排序则会打乱两个人的相对位置,也许对于结果来说有的时候会看不出来。
冒泡排序(Bubble Sort):是一种逻辑简单,算法方便的排序,每一趟可以定位一个数,共 需要n-1趟,每一趟都需要重复的遍历数组,两两比较,以确定需要定位的数。
选择排序(Selection Sort):是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
插入排序(Insertion Sort):是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
希尔排序(Shell Sort):也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。
归并排序(Merge Sort):是创建在归并操作上的一种有效的排序算法。该算法是采用分治法的一个非常典型的应用,简单来说,就是将数据分为单个元素,然后对其合并排序。
快速排序(Quick Sort):在平均状况下,排序 n 个项目要Ο(n log n)次比较。在最坏状况下则需要Ο(n²)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环可以在大部分的架构上很有效率地被实作出来。
鸽巢排序(Pigeonhole Sort):也被称作基数分类,是一种时间复杂度为O(n)且在不可避免遍历每一个元素并且排序的情况下效率最好的一种排序算法。但它只有在差值(或者可被映射在差值)很小的范围内的数值排序的情况下实用。
堆排序(Heap Sort):是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
适用场景:平均时间复杂度为O(n²)的有:插入排序,选择排序,冒泡排序, 在数据规模较小时,插入排序,选择排序差不多。当数据较大时,冒泡排序算法的时间代价最高。性能为O(n²)的算法基本上是相邻元素进行比较,基本上都是稳定的。
平均时间复杂度为O(nlogn)的有:快速排序,归并排序,希尔排序,堆排序。其中,快排是最快的,其次是归并排序和希尔排序,堆排序在数据量很大时效果优于其他排序方法。
总结:
当数据规模较小,对稳定性无要求时适用插入、选择、和冒泡排序,若对稳定性有要求,则不适合用插入排序,当数据基本有序时,插入排序的效率较高;
当数据规模较大时,适用快排,堆排希尔排序,归并排序;其中快排效率较高,且适用于大多数情况,堆排对于数据庞大的排序优于其他排序,归并为稳定性排序,其需要额外空间,若数据量较小,不推荐使用,希尔排序对于处理基本有序的数据,效率较高。
鸽巢排序:一般不推荐使用此排序,其使用场景比较少,算法不够简便,速度也略差于其他排序算法,它只有在数据较为集中时比较适用,当数据跨度过大,其效率会有很明显的下降,所以一般不使用。