算法-排序 快速排序
- 快速排序是一种使用很广泛的排序算法。
- 快速排序和归并排序差不多,都是将一个大的数组分为两个小的数组,然后两个小的数组分别排序。
- 不同点:归并排序是先将子数组排序,然后两个子数组在归并成一个数组,而快速排序在两个子数组有序之后自然就有序了,因为快速排序是在原数组上排序。
实现
- // 切分,获取基准位置,将数组分为两个小数组,基准位置左边的都是比基准元素小的,右边的都是比基准元素大的。
private static int partition(Comparable[] a, int low, int hi){ //切分
int i = low, j = hi+1;
Comparable v =a[low];
while (true){
while (less(a[++i],v)){ // a[i]都是小于v的元素,碰到大于v的元素就跳出该循环
if (i == hi)
break;
}
while (less(v,a[--j])) { //a[j]都大于v的元素,碰到小于v的元素就跳出该循环
// if (j == low) // 因为low处元素是基准元素,而a[j]元素要大于v递减,当减到了low处就会跳出循环
// break;
}
if (i >= j) // 找到基准位置
break;
exch(a, i, j);
}
exch(a, low, j);
return j;
}
- 排序-递归
public static void sort(Comparable[] a, int low, int hi){
if (hi <= low) //递归需要有结束条件,当子数组只有一个元素时就不需要进行切分。
return;
int j = partition(a,low,hi);
sort(a, low, j-1); // 左半部分排序
sort(a,j+1, hi); //右半部分排序
}
- 其他:
// 比较函数,判断v,w大小
public static boolean less(Comparable v, Comparable w){
return v.compareTo(w) < 0; // v<w
}
// 在数组a上交换两个元素位置
public static void exch(Comparable[] a, int i, int j){
Comparable t = a[i]; // 交换两个值的位置
a[i] = a[j];
a[j] = t;
}
- 优点
- 原地排序(只需要一个很小的辅助空间)
- 运行时间和NlgN成正比 ,是线性对数数量级
- 缺点:比较脆弱,代码实现过程很脆肉
一点小改进
当子数组比较小时,使用插入排序比快速排序要快。
小数组定义一般选5-15合适。
public static void sort(Comparable[] a, int low, int hi){
// if (hi <= low)
// return;
if (hi <= low+15)
Insertion.sort(a,low,hi);
int j = partition(a,low,hi);
sort(a, low, j-1); // 左半部分排序
sort(a,j+1, hi); //右半部分排序
}