建议可以先看看这篇文章,可以更好理解随机快排——随机快排时间复杂度是N平方?(讲述了数组分区、荷兰国旗问题,快排1.0版本如何进化到快排3.0版本)
package com.harrison.class03;
import javax.annotation.Resources;
import java.util.Stack;
/**
* @author Harrison
* @create 2022-02-28-15:15
* @motto 众里寻他千百度,蓦然回首,那人却在灯火阑珊处。
*/
public class Code07_QuickSortRecursiveAndUnrecursive {
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static int[] netherlandsFlag(int[] arr,int L,int R){
if(L>R){
return new int[]{-1,-1};
}
if(L==R){
return new int[]{L,R};
}
int less=L-1;
int more=R;
int index=L;
while(index<more){
if(arr[index]==arr[R]){
index++;
}else if(arr[index]<arr[R]){
swap(arr,index++,++less);
}else{
swap(arr,index,--more);
}
}
swap(arr,more,R);
return new int[]{less+1,more};
}
// 快速排序递归版本
public static void quickSort1(int[] arr){
if(arr==null || arr.length<2){
return ;
}
process1(arr,0,arr.length-1);
}
public static void process1(int[] arr,int L,int R){
if(L>=R){
return ;
}
swap(arr,L+(int)(Math.random()*(R-L+1)),R);
int[] lessEqual=netherlandsFlag(arr,L,R);
process1(arr,L,lessEqual[0]-1);
process1(arr,lessEqual[1]+1,R);
}
// 快速排序非递归版本辅助类
// 要处理的是什么范围上的排序
public static class Op{
public int l;
public int r;
public Op(int left,int right){
l=left;
r=right;
}
}
// 快速排序非递归版本
public static void quickSort2(int[] arr){
if(arr==null || arr.length<2){
return ;
}
int N=arr.length;
swap(arr,(int)(Math.random()*N),N-1);
int[] equalArea=netherlandsFlag(arr,0,N-1);
Stack<Op> stack=new Stack<>();
stack.push(new Op(0,equalArea[0]-1));
stack.push(new Op(equalArea[1]+1, N-1));
while(!stack.isEmpty()){
Op op=stack.pop();
if(op.l<op.r){
swap(arr,op.l+(int)(Math.random()*(op.r-op.l+1)),op.r);
equalArea=netherlandsFlag(arr,op.l,op.r);
stack.push(new Op(op.l,equalArea[0]-1));
stack.push(new Op(equalArea[1]+1, op.r));
}
}
}
public static int[] generateRandomArray(int maxSize, int maxValue) {
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
}
// 拷贝数组(用于测试)
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
// 对比两个数组(用于测试)
public static boolean isEqual(int[] arr1, int[] arr2) {
if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
return false;
}
if (arr1 == null && arr2 == null) {
return true;
}
if (arr1.length != arr2.length) {
return false;
}
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
// 打印数组(用于测试)
public static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
// 跑大样本随机测试(对数器)
public static void main(String[] args) {
int testTime = 500000;
int maxSize = 100;
int maxValue = 100;
boolean succeed = true;
System.out.println("test begin");
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
quickSort1(arr1);
quickSort2(arr2);
if (!isEqual(arr1, arr2)) {
succeed = false;
break;
}
}
System.out.println("test end");
System.out.println("测试" + testTime + "组是否全部通过:" + (succeed ? "是" : "否"));
}
}