快速排序
在每一轮挑选一个基准元素,并让其他比它大的元素移动到数列一边,比它小的元素移动到数列的另一边,从而把数列拆解成了两个部分。
随机快速排序的细节和复杂度分析
可以用荷兰国旗问题来改进快速排序 时间复杂度O(N*logN),额外空间复杂度O(logN)
public class QuickSort {
public static void main(String[] args) {
int[] arr = {5,8,6,2,4,3};
quickSort(arr);
for (int i : arr) {
System.out.print(i+" ");
}
}
/**
* 快速排序,使得整数数组 arr 有序
*/
private static void quickSort(int[] arr) {
if (arr == null||arr.length < 2){
return;
}
quickSort(arr,0,arr.length-1);
}
/**
* 快速排序,使得整数数组 arr 的 [L, R] 部分有序
*/
public static void quickSort(int[] arr,int l,int r){
if (l<r){
//让数组把r位置的数与随机位置的数交换,可以不需要
// 把数组中随机的一个元素与最后一个元素交换,这样以最后一个元素作为基准值实际上就是以数组中随机的一个元素作为基准值
// swap(arr,l+(int)(Math.random()*(r-l+1)),r);
//partition函数将arr数组[l,r]交换数据位置使部分有序,返回部分的第一个元素的下标和最后一个下标组成的整数数组
int[] p = partition(arr,l,r);
//子过程左部分中开始递归,使其有序
quickSort(arr,l,p[0]-1);
//子过程右部分开发递归,使其有序
quickSort(arr,p[1]+1,r);
}
}
/**
* 分区的过程,整数数组 arr 的[L, R]部分上,使得:
* 大于 arr[R] 的元素位于[L, R]部分的右边,但这部分数据不一定有序
* 小于 arr[R] 的元素位于[L, R]部分的左边,但这部分数据不一定有序
* 等于 arr[R] 的元素位于[L, R]部分的中间
* 返回等于部分的第一个元素的下标和最后一个下标组成的整数数组
*/
public static int[] partition(int[] arr, int l , int r){
int less = l-1;
int more = r;
int num = arr[r];
while (l<more){
if (arr[l]<num){
swap(arr, ++less, l++);
}else if (arr[l]>num){
swap(arr, --more,l);
}else {
l++;
}
}
swap(arr,more,r);
return new int[] {less+1,more};
}
public static void swap(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}