定义:
将一个序列经过一次排序后分成两部分,其中一部分的关键字都比另一部分大,然后再分别对这两部分继续进行排序,直到得到一个有序的序列。
时间复杂度:O(nlogn)
空间复杂度:O(logn)
实现
public class Quick {
public void sort(int[] arr){
qsort(arr,0,arr.length-1);
}
private void qsort(int[] arr,int low,int high){
if(low<high){
int pivot=partion(arr,low,high);
qsort(arr,low,pivot);
qsort(arr,pivot+1,high);
}
}
private int partion(int[] arr,int low,int high){
int shuzhou=arr[low];
while(low<high){
while(low<high && shuzhou<=arr[high]){
high--;
}
SortUtils.swap(arr,low,high);
while(low<high && shuzhou >=arr[low]){
low++;
}
SortUtils.swap(arr,low,high);
}
System.out.print("枢轴:"+shuzhou+",序列:");
SortUtils.print(arr);
return low;
}
public static void main(String[] args){
int[] arr=SortUtils.getArray();
SortUtils.print(arr);
Quick quick=new Quick();
quick.sort(arr);
}
}
算法优化:
1、枢轴优化
什么是枢轴?当序列被分成两部分时,处在中间“分水岭”位置的关键字就是枢轴,所以当枢轴接近所有关键字的中位数时,效率较高,所以枢轴的选取就成为可以优化提高性能的地方。
常用优化方法:随机枢轴、抽样取中等
以抽样取中为例,当记录数较小时,可以三数取中,既取三个关键字先进行排序,将中间的数作为枢轴。
实现:
在上面代码的partion方法中的第一行代码之前加入以下代码:
//三数取中
int mid=low+(high-low)/2;
if(arr[low]>arr[high]){
SortUtils.swap(arr,low,high);
}
if(arr[mid]>arr[high]){
SortUtils.swap(arr,mid,high);
}
if(arr[mid]>arr[low]){
SortUtils.swap(arr,mid,low);
}
之后low位置的数将是low、mid、high这三个数中的中间数
2、数据交换优化
在partion方法中可能会发生多次数据交换操作
int shuzhou=arr[low];
while(low<high){
while(low<high && shuzhou<=arr[high]){
high--;
}
SortUtils.swap(arr,low,high);
while(low<high && shuzhou >=arr[low]){
low++;
}
SortUtils.swap(arr,low,high);
}
当数据交换操作过于频繁时,无疑会影响性能,所以此处可以进行优化,将数据交换操作变为数据赋值,将以上代码改为:
int shuzhou=arr[low];
while(low<high){
while(low<high && shuzhou<=arr[high]){
high--;
}
arr[low]=arr[high];
while(low<high && shuzhou >=arr[low]){
low++;
}
arr[high]=arr[low];
}
arr[low]=shuzhou;
3、排序方案优化
随着排序的进行,序列不断被一分为二,于是子序列的长度不断变小,当子序列的长度足够小时,用快速排序算法就有点大炮打蚊子的感觉了,此时可以转而采用在小序列排序中效率最好的插入排序。
将qsort方法修改如下:
private void qsort(int[] arr,int low,int high){
if(high-low > 7){
int pivot=partion(arr,low,high);
qsort(arr,low,pivot);
qsort(arr,pivot+1,high);
}else{
this.insertion.sort(arr);
}
}
4、递归优化
递归操作需要占用一定的栈空间,递的次数越多、深度越多则需要的栈空间越多,快看算法中用到了递归操作,所以此处进行优化后可提高性能。
将qsort方法修改如下:
private void qsort(int[] arr, int low, int high) {
if (high - low > 7) {
while (low < high) {
int pivot = partion(arr, low, high);
qsort(arr, low, pivot);
low=pivot+1;
}
} else {
this.insertion.sort(arr);
}
}
将原来的两次递归操作改为一次递归加迭代,降低了递归的深度。