基本思想
选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其拍好序后的正确位置,然后再用同样的方法递归地排序划分地两部分
int a[] ={2,45,435,4,4,2,321,25,34,57};
@Test
public void quickSort(){
int[] tem = quickSort(a,0,a.length-1);
System.out.println(Arrays.toString(tem));
}
private int[] quickSort(int[] arr,int left,int right){
if(left<right){
//找到pivot的位置,左侧都小于它,右侧都大于它
int partitionIndex=partition(arr,left,right);
//左侧
quickSort(arr,left,partitionIndex-1);
//右侧
quickSort(arr,partitionIndex+1,right);
}
return arr;
private int partition(int[] arr,int left,int right){
//设定基准值(pivot),以左边数字为基准
int pivot = left;
//左侧寻找
int index = pivot + 1;
//保证index坐标左侧的都小于pivot值
for(int i=index;i<=right;i++){
if(arr[i]<arr[pivot]){
swap(arr,i,index);
index++;
}
}
//确定pivot的位置
swap(arr,pivot,intex -1);
//返回pivot的索引值
return index -1;
}
private void swap(int[] arr,int i,int j){
int temp =arr[i];
arr[i]=arr[j];
arr[j] = temp;
}
}
由以上代码可知,所划分的子序列并不是等长的。
改进的快速排序
为了尽可能地使划分的序列尽可能相同,只对长度大于k的子序列递归调用快速排序,让原序列基本有序,然后再对整个基本有序序列用插入排序算法排序。实践证明,改进后的算法时间复杂度有所降低,且 当k取值为8左右时,改进算法的性能最佳。
int[] a={23,45,535,2346,6,75,453,23};
public void quickSort(){
int[] arr =quickSort2(a,0,a.length-1,8);
for(int i =1; i<a.length;i++){
int temp = a[i];
int j;
for(j=i-1;j>=0 && a[j]>temp;j--){
a[j+1] = a[j];
}
a[j+1] = temp;
}]
System.out.println(Arrays.toString(arr));
}
public int[] quickSort2(int[] a,int low,int high,int k){
if(high - low > k){
int pivot = partition(a,low,high);
quickSort2(a,low,pivot -1,k);
quickSort2(a,pivot+1,high,k);
}
return a;
}
private int partition(int[] a,int low,int high){
//表两端交替向中间扫描,最多到low+1
//比基准小交换到低端
while(low < high){
while(low < high && a[high] >=pivot){
high--;
}
swap(a,low,high);
while(low < high && a[low] <= pivot){
low++;
}
swap(a,low,high);
}
return low;
}
private void swap(int[] arr ,int i,int j){
int temp = arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
- 时间复杂度: O(nlogn)
- 空间复杂度:O(nlogn)
以上,所谓快排的改进无非是确定 基准位置的方式以及分治划分区域的优化