快速排序的优化过程可以参考我的另一篇博文:《快速排序及其优化过程总结》
快排示意图:
/**
* 快速排序
*/
public class test2_8 {
static Comparable a[] = {"49","38","65","97","76","13","27"};
private static void qSort(int left,int right){
if(left<right){
//定位并使定位好的元素左边都比其小,右边都比其大
int mid = partition(left,right);
//递归
qSort(left,mid-1);
qSort(mid+1,right);
}
}
private static int partition(int left,int right){
int i=left,j=right+1;
Comparable x = a[left],temp;
while(true){
//寻找第一个比x元素大的元素的下标
while(a[++i].compareTo(x)<0&&i<right);
//寻找第一个比x元素小的元素的下标
while(a[--j].compareTo(x)>0);
if(i>=j){
a[left] = a[j];
a[j] = x;
break;
}
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
return j;
}
public static void main(String[] args) {
System.out.print("排序前:");
for(int i=0;i<a.length;i++)
System.out.print(a[i]+" ");
System.out.println();
qSort(0,a.length-1);
System.out.print("排序后:");
for(int i=0;i<a.length;i++)
System.out.print(a[i]+" ");
}
}
运行结果如下:
排序前:49 38 65 97 76 13 27
排序后:13 27 38 49 65 76 97
总结:
①细心的读者会发现第20行代码和第22行代码
while(a[++i].compareTo(x)<0&&i<right);
while(a[--j].compareTo(x)>0);
两行代码的区别是i<right
条件,为什么第一行多了这个条件而第二行代码却没有这个条件呢?
原因如下:a[left](即数组的首元素)后面的元素都有可能比其本身小,没有约束的遍历下去可能会导致数组下标越界,因为++i
表明其最多只能遍历n-1个元素(一开始i=left
),无法遍历到数组首元素。而不对--j
加条件的原因是一开始j=right+1
,所以第一遍--j
后j
就能率先遍历到最后一个元素,然后依次向前,最多可遍历n个数组元素
②break;
语句前第24行代码是a[left] = a[j];
而不是a[left] = a[i];
为什么呢?
因为如果i
≠j
,则i
下标对应的数组元素一定比x元素大,而j
下标对应的数组元素一定比x元素小,快排中(升序情况下)选中元素x左边的元素都比其小,右边的必须比其大,所以应该把比x元素小的元素和x元素交换位置,使其位于x元素左边。