各种排序方法的比较
排序方法有很多,它们各有优缺点,没有绝对最好的和最坏的排序方法,只有最符合某个使用场景的方法。在选用排序方法的时候,我们应该综合考虑以下方面:
1)时间复杂度;
2) 空间复杂度;
3)稳定性;
4)算法简单性;
5)待排序记录个数n的大小;
6)记录本身信息量的大小;
7)关键码的分布情况;
下面先从每个方面逐个对常用的一些算法进行比较和分析,然后给出综合讨论。
一、时间复杂度和空间复杂度
排序方法 | 平均情况 | 最好情况 | 最坏情况 | 辅助空间 |
冒泡排序(交换排序) | O( | O(n) | O( | O(1) |
快速排序(冒泡排序的一种改进) | O( | O( | O( | O( |
直接插入排序(插入排序) | O( | O(n) | O( | O(1) |
希尔排序(直接插入排序的一种改进) | O( | O( | O( | O(1) |
简单选择排序(选择排序) | O( | O( | O( | O(1) |
堆排序(简单选择排序的一种改进) | O( | O( | O( | O(1) |
归并排序 | O( | O( | O( | O(n) |
桶式排序(分配排序之一) | ||||
基数排序(分配排序之一) | O(d(n+m)) | O(d(n+m)) | O(d(n+m)) | O(m) |
二、稳定性
给定一个原始记录序列,其相应的关键码分别是
。如果,在原序列中,
=
,且
在
之前,在排序后的序列中,
仍在
之前,则这种排序算法稳定;否则称为不稳定。
稳定的排序方法 | 直接插入排序、冒泡排序、归并排序和基数排序 |
不稳定的排序方法 | 希尔排序、快速排序、简单选择排序和堆排序 |
三、算法简单性
简单方法 | 冒泡排序、直接插入排序算法、简单选择排序、桶式排序 |
改进方法 | 快速排序、希尔排序、堆排序、归并排序、基数排序 |
四、待排序的记录个数n的大小
n越小,采用简单排序方法越合适;n越大,采用改进的排序方法越合适。( 因为n越小,O()和O(
)的差距就越小,并且输入和调试简单算法比输入和调试改进算法要少用许多时间。)
五、一个记录包含的信息量的大小
一个记录包含的信息量越大,占用的存储空间就越多,移动记录所花费的时间就越多,所以对记录的移动次数较多的算法不利。
三种简单排序方法中记录的移动次数的比较 | |||
排序方法 | 最好情况 | 最坏情况 | 平均情况 |
直接插入排序 | O(n) | O( | O( |
冒泡排序 | 0 | O( | O( |
简单选择排序 | 0 | O(n) | O(n) |
从上表可以看出,当记录包含的信息量较大时,选择简单选择排序会获得比其他两种排序方法更好的排序效率。这里还有一种方法可以减少移动记录的时间,尤其是当记录包含的信息较多时,可以使用数组的每一个元素存储指向记录的指针,在这种情况下,移动只需要对指针进行操作(增加了空间,但节省了时间)。
六、关键码的分布情况
当待排序记录序列符合期望的序列时,这对直接插入排序和冒泡排序来说是最好的情况,但对快速排序来说是最坏的情况。简单选择排序、堆排序、归并排序和基数排序的时间性能与关键码的分布情况无关。
综合考虑以上六个方面,可以有以下大致结论:
(1)当待排序记录个数n较大,关键码分布较随机,且对稳定性不作要求时,宜采用快速排序。
(2)当待排序记录个数n较大,内存空间允许,且要求排序稳定时,采用归并排序为宜。
(3)当待排序记录个数n较大,关键码分布可能出现正序(已经排好顺序)或者逆序(与期待的顺序相反)的情况,且对稳定性不做要求时,采用堆排序或归并排序。
(4) 当待排序记录个数n较大,而只要找出最小的前几个记录,采用堆排序或简单选择排序。例如,在堆排序中,如果想找到序列中第k大的记录,则需要O(n+)时间;如果k很小,这会快很多。
参考书籍:
数据结构(C++版)王红梅 胡明 王涛 编著