一、基本思路
1.在当前要排序的区间选择一个基准值x,并令i指向区间最左,j指向区间最右
2.从该区间 j 的位置向左开始扫描,直到找到一个比基准值x小的, 将这个小的填到 i 的位置上,i++;
3.从该区间 i 的位置向右开始扫描,直到找到一个比基准值x大的,将这个大的填到 j 的位置上,j–;
4.重复2,3 直到 i 超过 j 或等于 j ,此时将基准值x填入a[ i ],至此,x左边的所有数都比 x 小,右边的所有数都比 x 大
5.以 i 为分界线,分别对区间 [ l ,i-1 ] ,[ i+1,r ]进行快排
二、例子
我们以{3,5,7,9,8,6,2,1,4,0}数组的排序为例子,我们可以将要被填的地方看成一个坑
1.令基准值为区间第一个,也就是x=3,i,j 的位置如下,此时i的位置是一个坑,需要被填,所以要从后面找一个比x小的来填
i j
3 | 5 | 7 | 9 | 8 | 6 | 2 | 1 | 4 | 0 |
2.从 j 开始往左找一个比 x 小的,此时我们找到一个0,将0填到 i 这个坑的位置上,并将 i++ ,如下
i j
0 | 5 | 7 | 9 | 8 | 6 | 2 | 1 | 4 | 0 |
此时由于 j 这个地方的数移到了前面,落下了一个坑,所以要从前面找一个比 x 大的数来填补这个坑
3.从i开始往右找一个比 x 大的,此时我们找到一个5,将5填到 j 这个坑的位置上,并将 j–,如下
i j
0 | 5 | 7 | 9 | 8 | 6 | 2 | 1 | 4 | 5 |
此时由于i这个地方的数移到了后面,又落下一个坑,所以要从后面找一个比 x 小的数来填补这个坑
2.从 j 开始往左找一个比 x 小的,此时我们找到一个1,将1填到i的位置上,并将 i++ ,如下
i j
0 | 1 | 7 | 9 | 8 | 6 | 2 | 1 | 4 | 5 |
3.从 i 开始往右找一个比 x 大的,此时我们找到一个7,将7填到j的位置上,并将 j– ,如下
i j
0 | 1 | 7 | 9 | 8 | 6 | 2 | 7 | 4 | 5 |
2.从 j 开始往左找一个比 x 小的,此时我们找到一个2,将2填到i的位置上,并将 i++ ,如下
i j
0 | 1 | 2 | 9 | 8 | 6 | 2 | 7 | 4 | 5 |
3.从 i 开始往右找一个比 x 大的,此时我们找到一个9,将9填到j的位置上,并将 j–,如下
i j
0 | 1 | 2 | 9 | 8 | 6 | 9 | 7 | 4 | 5 |
2.从j开始往左找一个比 x 小的,此时我们的j一直移到了i的那个位置,也找不到比3更小的了,我们将 i 的位置填上这个基准数
i,j
0 | 1 | 2 | 3 | 8 | 6 | 9 | 7 | 4 | 5 |
4.到了这一步,我们可以发现 i 位置的左边均比a[i]小,右边均比a[i]大 ,i=3
5. 继续对 [0,2],[4,9] 区间分别快排
三、代码实现
public class QuickSort {
public static void main(String[] args) {
int [] a=new int[]{3,5,7,9,8,6,2,1,4,0};
QuickSort quickSort=new QuickSort();
quickSort.quickSort(a,0,9);
for(int item:a){
System.out.print(item+" ");
}
}
private void quickSort(int[] a, int l, int r) {
if(l<r){
int i=l,j=r,x=a[l];//定义基准数x(区间第一个),以及i,j指标
while(i<j){
while(i<j&&a[j]>=x)//从最右边开始找一个比x小的
j--;
if(i<j)//此时j所指的数比x小
a[i++]=a[j];
while(i<j&&a[i]<=x)//从最左边开始找一个比x大或相等的
i++;
if(i<j)//此时i所指的数比x大或相等
a[j--]=a[i];
}
a[i]=x; //一趟下来x左边的所有数比x小,...
quickSort(a, l, i-1);
quickSort(a, i+1, r);
}
}
}
四、复杂度
最优情况下,也就是每次选的基准值都是中位数,每次都划分得很均匀 ,此时时间复杂度为O(nlogn)
最差情况下,是待排序数组刚好是正序或逆序,如刚好是正序,那么每一次的基准值会填入在区间最左边,然后递归右边的子区间,如[ 1,9 ]、[ 2,9 ]、[ 3,9 ]、[ 4,9 ]、[ 5,9 ]……由于左边的区间是[0,-1],[1,0],[2,1],左大于右,故会终结递归,所以考虑到右边的区间递归,为 O(n²)
平均情况下,为O(nlogn)