快排将整个数组分为两部分,大于主元的在右边小于主元的在左边,这个操作可以通过单指针扫描来完成,也可以通过双指针扫描来完成,单指针扫描简单易理解,双指针扫描快一点。
通过对分区的操作,我才理解了快排的思想主要集中在数组的 分开 上, 而归并排序的时间主要花在了合并上。
代码如下;
package L3;
import java.util.Arrays;
public class L2 {
// 快排一遍单向扫描法
static int pv(int[] a, int l, int r) {
int pivot = a[l];// 定主元
int sp = l + 1;// 扫描指针
int bigger = r;
while (sp <= bigger) {
if (a[sp] <= pivot)
sp++;
else {
int t = a[sp];
a[sp] = a[bigger];
a[bigger] = t;
bigger--;
}
}
int t = a[l];
a[l] = a[bigger];
a[bigger] = t;
System.out.println(Arrays.toString(a));
return bigger;
}
// 快排双向扫描指针
static int pv2(int[] a, int l, int r) {
int pivot = a[l];
int left = l + 1;// 左指针
int right = r;// 右指针
while (left <= right) {
// left向右走,直到遇见大于主元的元素
while (left <= right && a[left] <= pivot)
left++;
while (left <= right && a[right] > pivot)
right--;
if (left < right) {
int t = a[left];
a[left] = a[right];
a[right] = t;
}
}
// while退出时,两者交错,且right指向最后一个小于等于主元的元素,也就是主元应该呆的位置
int t = a[l];
a[l] = a[right];
a[right] = t;
System.out.println(Arrays.toString(a));
return right;
}
static void quick(int[] a, int l, int r) {
if (l < r) {
int q = pv2(a, l, r);
quick(a, l, q - 1);
quick(a, q + 1, r);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = { 1, 8, 0, 7, 5, 91, 12 };
System.out.println(Arrays.toString(a));
quick(a, 0, a.length - 1);
System.out.println(Arrays.toString(a));
}
}