核心思想:从要排序的一组数据中取出任意一个数x,作为分区点,将小于x的数放到其左边,将大于x的数放到其右边,x放中间,这就完成了一次处理。
一次操作后将数据分为了三部分,小于x的部分,x和大于x的部分,其中小于x和大于x的部分,分别重复上面的操作,即每个数据组任取一个数作为分区点,继续比较将数据分区。
看下面的例子:
[3, 2, 6, 10, 7, 1, 8, 5] | 取分区点为数组最后一个数,值为5
[3, 2, 1] 5 [6, 10, 7, 8] | 数组分为了三个部分
空 1 [3, 2] [6, 7] 8 [10] | 两个子数组各自分为了三个部分
空 2 [3] | 重复以上步骤
[1, 2, 3, 5, 6, 7, 8, 10] | 最终没有要处理的数据,那么数组已经有序了
快排依旧是分治思想,递归处理。
每次排序都是将数组分为两部分,所以递推公式的重点就是找到两部分数据的区间
递推公式: quickSort(arrs,start,mid-1)+quickSort(arrs,mid+1,end)
代码:
public static void sort(int[] arrs, int start, int end) {
if(start >= end) {return;}
int mid = partition(arrs, start, end);
sort(arrs, start, mid-1);
sort(arrs, mid+1, end);
}
public static int partition(int[] arrs, int start, int end) {
int pivot = arrs[end];
int i = start;
for(int j=start; j<end; j++) {
if(arrs[j]<pivot) {
int temp = arrs[i];
arrs[i] = arrs[j];
arrs[j] = temp;
i++;
}
}
int temp = arrs[i];
arrs[i] = arrs[end];
arrs[end] = temp;
System.out.println();
System.out.println("排序后的数组:");
Arrays.stream(arrs).forEach(x->System.out.print(x + " "));
return i;
}
输出:
排序前的数组:
6 2 7 1 2 11 3 21 15 10
排序中间值:
6 2 7 1 2 3 10 21 15 11
排序中间值:
2 1 2 3 7 6 10 21 15 11
排序中间值:
1 2 2 3 7 6 10 21 15 11
排序中间值:
1 2 2 3 6 7 10 21 15 11
排序中间值:
1 2 2 3 6 7 10 11 15 21
排序中间值:
1 2 2 3 6 7 10 11 15 21
排序后的数组:
1 2 2 3 6 7 10 11 15 21
快速排序的时间复杂度O(nlogn),极端情况下会退化为O(n^2),空间复杂度为O(1)。