概念和思想
-
从数列中挑出一个元素,称为“基准”(pivot)
-
分区(partition): 遍历数列,比基准小的元素放左边,比它大的放右边。
于是此次分区结束后,该基准就处于数列的中间位置,其左边的数全比它小(称为小与子序列),右边的数全比他大(称为大于子序列)。这样一次排序就造成了整体上的有序化。 -
子数列排序: 将小与子数列和大于子序列分别继续快速排序。
-
递归到最底部时,数列的大小是零或一,至此就都排序好了,递归结束。
看了图就知道,其实就只将整体分为两区域,成为分区,即partition,而分界线也就是基准元素位置是就位的,接下来对左边分区和右边分区继续进行这个思路来partition,利用递归直至全部元素就位达到排序目的。
双边循环法 & 单边循环法
双边循环法
有很多方法,这是最基本最普通的方法
再来一个演示过程的图,加深理解
单边循环法
code
public class Tss {
//main方法中将数组传入排序方法中处理,之后打印新的数组
public static void main(String[] stra){
int[] arr={
7,0,3,5,4,6,2,8,1,9};
quickSort(arr, 0, arr.length-1);
for (int i=0;i<arr.length;i++) {
System.out.print(arr[i]+"、");
}
}
public static void quickSort(int[] arr, int startIndex, int endIndex) {
// 递归结束条件:startIndex大于或等于endIndex时
if (startIndex >= endIndex) {
return;
}
// 得到基准元素位置
int pivotIndex = partition2(arr, startIndex, endIndex);
// 根据基准元素,分成两部分进行递归排序
quickSort(arr, startIndex, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, endIndex);
}
/**
* partition即就是进行一次分区,利用分治法,同时得到基准元素位置(双边循环法)
*/
private static int partition(int[] arr, int startIndex, int endIndex) {
// 取第1个位置(也可以选择随机位置)的元素作为基准元素
int pivot = arr[startIndex];
int left = startIndex;
int right = endIndex;
while( left != right) {
//控制right 指针比较并左移
while(left<right && arr[right] > pivot){
right--;
}
//控制left指针比较并右移
while( left<right && arr[left] <= pivot) {
left++;
}
//交换left和right 指针所指向的元素
if(left<right) {
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
}
//pivot 和指针重合点交换
arr[startIndex] = arr[left];
arr[left] = pivot;
return left;
}
/**
* partition即就是进行一次分区,利用分治法,同时得到基准元素位置(单边循环法)
*/
private static int partition2(int[] arr, int startIndex, int endIndex) {
// 取第1个位置(也可以选择随机位置)的元素作为基准元素
int pivot = arr[startIndex];
int mark = startIndex; //mark标记的是坐标,最后要将pivot和mark坐标元素swap,得到pivot分割后的左小右大两个区域
for(int i=startIndex+1; i<=endIndex; i++){
if(arr[i]<pivot){
mark ++; // 每次+1,是统计有多少个小于pivot的元素,
int p = arr[mark]; //同时将小于pivot的元素交换位置,交换到mark标记的左侧区域,也就是小于pivot的区域
arr[mark] = arr[i];
arr[i] = p;
}
}
// 上面代码是为了分区,以及得到mark坐标,此时将pivot和mark元素交换,利用pivot分区完毕
arr[startIndex] = arr[mark];
arr[mark] = pivot;
return mark;
}
}