稳定性:如果一个排序算法能够保留数组中重复元素的相对位置则可以被称为是稳定的。例如,一组数据先按照时间排序,再按照地理位置排序。如果第二次排序的排序算法具有稳定性,那么相同地理位置的数据还是按照时间排序的。
只有插入排序、冒泡排序和归并排序是稳定的。
各种排序算法的性能特点:
算法 | 是否稳定 | 是否为原地排序 | 时间复杂度 | 空间复杂度 | 备注 |
选择排序 | 否 | 是 | N² | 1 | |
冒泡排序 | 是 | 是 | 介于N和N²之间 | 1 | |
插入排序 | 是 | 是 | 介于N和N²之间 | 1 | 取决于输入元素的排列情况 |
希尔排序 | 否 | 是 | 近似于NlogN | 1 | |
快速排序 | 否 | 是 | NlogN | lgN | 运行效率由概率提供保证 |
三向快速排序 | 否 | 是 | 介于N和NlogN之间 | lgN | 运行效率由概率保证,同时也取决于输入元素的分布情况 |
归并排序 | 是 | 否 | NlogN | N | |
堆排序 | 否 | 是 | NlogN | 1 |
应用选择:
①大多数实际情况中,快速排序是最佳选择;但是如果稳定性很重要,而空间又不是问题,归并排序可能是最好的。
②将原始数据类型排序:一些性能优先的应用的重点可能是将数字排序,因此更合理的做法是跳过引用在直接将原始数据类型排序。例如,将double类型的数组和Double类型的数组排序有很大差别,前者可以直接交换这些数,而后者我们交换的是存储了这些数字的Double对象的引用。具体方法是把Comparable借口替换为原始数据类型名,重定义less()方法或者干脆将调用less方法的地方替换为a[i]<a[j]这样的代码。
Java系统库的排序算法:
Java系统库中的主要排序方法java.util.Arrays.sort()。根据不同的参数leixing,他实际上代表了一系列的排序方法。
①每种原始数据类型都有一个不同的排序方法;
②一个适用于所有实现了Comparable接口的数据类型的排序算法;
③一个适用于实现了比较器Comparable的数据类型的排序算法。
Java程序员算着对原始数据类型使用(三向切分的)快速排序;对引用类型使用归并排序(稳定性)。