一、算法思想
快速排序(Quick Sort)使用分治法策略。它的基本思想是:选择一个基准数,通过一趟排序将要排序的数据分割成独立的两部分;其中一部分的所有数据都比另外一部分的所有数据都要小。然后,再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
二、算法流程
(1) 从数列中挑出一个基准值。
(2) 将所有比基准值小的摆放在基准前面,所有比基准值大的摆在基准的后面(相同的数可以到任一边);在这个分区退出之后,该基准就处于数列的中间位置。
(3) 递归地把"基准值前面的子数列"和"基准值后面的子数列"进行排序。
三、算法实现
//快速排序
static class QuickSort implements Sort {
@Override
public String sortName() {
return "快速排序";
}
@Override
public Comparable[] sort(Comparable[] data) {
int lo = 0, hi = data.length - 1;
sort(data, lo, hi);
return data;
}
//递归体
private static void sort(Comparable[] data, int lo, int hi) {
if(hi <= lo) return;
int partition = partition(data, lo, hi);
sort(data, lo, partition - 1);
sort(data, partition + 1, hi);
}
//分组
private static int partition(Comparable[] data, int lo, int hi) {
//确定分界值
Comparable key = data[lo];
//定义两个指针,分别指向待切分元素的最小索引处和最大索引处的下一个位置
int left = lo, right = hi + 1;
//切分
while(true) {
//先从左往右扫描,移动right指针,找到一个比分界值小的元素,停止
while(!Sort.greater(key, data[--right])) {
if(right == lo) break;
}
//再从左往右扫描,移动left指针,找到一个比分界值大的元素,停止
while(!Sort.greater(data[++left], key)) {
if(left == hi) break;
}
//判断left>=right,如果是,则证明元素扫描完毕,结束循环,如果不是,则交换元素即可
if(left >= right) {
break;
} else {
Sort.swap(data, left, right);
}
}
//交换分界值
Sort.swap(data, lo, right);
return right;
}
}
四、算法分析
复杂度
稳定性
快速排序出于性能上的考虑,牺牲了算法的稳定性。虽然可以改变交换规则,使得算法保持稳定性,但却牺牲了性能,对于一个排序算法而言,这是得不偿失的,除非是上下文有稳定性方面的需求,否则,不建议改变交换规则。