第一步:设定一个分界值,通过该分界值将数组分成左右两边。(一般取第一个元素)
第二步:将大于或等于分界值放在数组右边,将小于或等于分界值放在数组左边。
第三步:左边和右边的数据可以独立排序。对于左侧的数据又可以取一个分界值,将该部分数据分成左右两更小部分,同样左边放较小值,右边放较大值。右侧数据也做一样的处理。
第四步:递归将左侧数据排序后,再递归排好右侧部分。当左侧和右侧数组都排好序后,整个数组就排好序了
其中排序分组的步骤:
1.找一个基准值(第一个元素),用两个指针指向数组头部与尾部。
2.先从尾部往头部开始搜索一个比基准值小的元素,搜索到即停止,并记录指针位置。(当右指针一直遍历到头部才停止说明数组有序,直接跳出当前循环)
3.再从头部往尾部开始搜索一个比基准值大的元素,搜索到即停止,并记录指针位置。(当左指针一直遍历到尾部才停止说明数组反序,直接跳出当前循环)
4.交换当前左右指针的元素
5.重复2.3.4直到两指针重合
6.每一次排序后 交换基准元素与指针重合位置的元素
快速排序图解:
分割并排序图解:
代码:
public class QuickSort {
public static void main(String[] args) {
int arr[]={6,5,4,3,2,1};
sort(arr,0,5);
System.out.println(Arrays.toString(arr));
}
public static void sort(int[] arr) {
int low=0;
int high=arr.length-1;
sort(arr,low,high);
}
//对arr数组中第low个到第high个进行排序
private static void sort(int[] arr,int low,int high) {
//安全性校验,当只有一个元素的时候不切分
if(high<=low){return;}
//对第low个到第high个数据进行分组
int partition=partition(arr,low, high);//返回的是排序分组后分界值位置变化后的索引
//对分组后的左边数据进行递归排序
sort(arr,low,partition-1);
//对分组后的右边数据进行递归排序
sort(arr,partition+1,high);
}
private static int partition(int[] arr,int low,int high) {
//基准值
int key=arr[low];
//两个指针
int right=high;
int left=low;
//切分
while(right>left){
while(arr[right]>key){
right--;
if(right==low)break;
}
//如果指针重合,则不再移动左指针
while(right>left&&arr[left]<=key){
left++;
if(left==high)break;
}
if(left<right){
//交换当前左右指针的元素
int temp=arr[right];
arr[right]=arr[left];
arr[left]=temp;}
}
//将基准值与指针重合位置的值交换
int temp=arr[right];
arr[right]=arr[low];
arr[low]=temp;
//返回当前的中间元素,以便对其前部分与后部分再次排序
return right;
}
}
最差时间复杂度:O( n^2 )
最好时间复杂度:O( nlog2n ) 数组本身有序的情况
非递归方法:
如果要非递归实现快速排序,在sort()方法内考虑使用stack栈,将左边界与右边界放入栈中,调用partition函数,参数从栈中取出,partition函数结束后,再放入分割后的两部分数组的左右边界。当栈为空,循环结束。