1.快速排序概述
快速排序在数组中选择一个基准值,将数组分为 两部分,第一部分的所有元素都小于或等于基准元素,第二部分都大于或等于基准元素,再分别对两部分递归调用排序算法
2.快速排序的基本步骤
1)找基准元素(以数组的第一个元素为例)
2)划分区域(使小的元素都在左边,大的元素都在右边)
3)递归调用排序算法
3.快速排序的划分区域算法
1)一遍单向扫描法
- 用两个指针sp和bigger将数组划分为3个区间
- 扫描指针sp是确认小于等于基准元素的,初始指向基准元素的下一个元素
- bigger指针指向数组最后一个元素(未知区间末指针),确认大于基准的元素
- 当扫描指针指向的值小于或等于基准值时,扫描指针继续向右移动
- 当扫描指针指向的值大于基准值的元素,和bigger指针指的元素交换,bigger指针向前移动
如图所示,一趟完成后此时bigger指针指向小于基准值的最后一个元素,sp指针指向大于基准值得第一个元素,所以,此时基准值和bigger指针指向的元素交换位置(基准值归位)
2)双向扫描法 - 定义两个指针left和right
- left指向基准元素后面的那个元素,right指向序列的最后一个元素
- left指针往中间扫描,从左边找到大于基准值的元素时停下,right指针向前扫描,从右边找小于等于基准值的元素时停下,此时二者交换,然后继续扫描,直到左侧无大元素,右侧无小元素
4.代码实现
1)一遍单向扫描法
/*
* 快排的划分算法1:
* 一遍单向扫描法
* 用两个指针将数组划分为3个区间
* 扫描指针左边是确认小于等于基准元素的
* bigger指针指向数组最后一个元素(未知区间末指针),确认大于基准的元素
* 当扫描指针指向的值小于基准值,扫描指针继续向右移动
* 当扫描指针指向的值大于基准值的元素,和bigger指针指的元素交换,bigger指针向前移动
*/
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
int[] array = {2,3,12,8,98,56,33,7,7};
quickSort(array,0,array.length - 1);
System.out.println(Arrays.toString(array));
}
public static void quickSort(int[] array, int begin, int end) {
if(begin < end) {
int q = partition(array,begin,end);//q为基准元素的位置
quickSort(array,begin, q - 1); //对左侧元素递归排序
quickSort(array,q + 1,end);//对右侧元素递归排序
}
}
public static int partition(int[] array, int begin,int end) {
int value = array[begin]; //基准元素
int sp = begin + 1; //左指针(扫描指针)
int bigger = end; //右指针
while(sp <= bigger) {
if(array[sp] <= value) { //比基准元素小,指针继续向前移动扫描
sp++;
}
else { //比基准元素大,先和bigger指向的元素交换,bigger指针向前移
int temp = array[bigger];
array[bigger] = array[sp];
array[sp] = temp;
bigger--;
}
}//一趟完成后,此时bigger指针指向最后一个小于基准元素的元素,sp指向第一个大于基准元素的值
int temp = array[bigger]; //基准元素归位
array[bigger] = array[begin];
array[begin] = temp;
return bigger;
}
}
2)双向扫描法
```java
/*
* 快排的划分算法2:
* 双向扫描法:
* 思路:头尾指针往中间扫描,从左边找到大于基准值得元素,从右边找小于等于基准值的元素,二者交换,继续扫描,直到左侧无大元素,右侧无小元素
*/
import java.util.Arrays;
public class QuickSort2 {
public static void main(String[] args) {
int[] array = {2,3,12,8,98,56,33,7,7};
quickSort(array,0,array.length - 1);
System.out.println(Arrays.toString(array));
}
public static void quickSort(int[] array, int begin, int end) {
if(begin < end) {
int q = partition(array,begin,end);
quickSort(array,begin, q - 1);
quickSort(array,q + 1,end);
}
}
public static int partition(int[] array, int begin,int end) {
int value = array[begin]; //基准元素
int left = begin + 1; //左指针(扫描指针)
int right = end; //右指针
while(left <= right) {
while(left <= right && array[left] <= value) {
left++;
}
while(left <= right && array[right] > value) {
right--;
}
if(left < right) {
int temp = array[left]; //左右指针所指向的值交换位置
array[right] = array[left];
array[left] = temp;
}
}
//循环退出时,两个指针位置交错,且right指向最后一个小于等于基准值的元素,left指向第一个大于基准值的元素。此时交换基准值和right所指向的元素
int temp = array[right];
array[right] = array[begin];
array[begin] = temp;
return right;
}
}