递归与非递归方式实现随机快排

简介: 递归与非递归方式实现随机快排

建议可以先看看这篇文章,可以更好理解随机快排——随机快排时间复杂度是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 ? "是" : "否"));
    }
}
相关文章
|
4月前
|
算法
【算法】递归总结:循环与递归的区别?递归与深搜的关系?
【算法】递归总结:循环与递归的区别?递归与深搜的关系?
111 0
|
7月前
|
搜索推荐
排序算法:快速排序(三种排序方式、递归和非递归)
排序算法:快速排序(三种排序方式、递归和非递归)
422 0
49 # 用递归和非递归两种方式实现链表反转
49 # 用递归和非递归两种方式实现链表反转
60 0
算法:分治思想处理快排递归以及快速选择/最小K个数问题
算法:分治思想处理快排递归以及快速选择/最小K个数问题
|
算法
【刷算法】翻转二叉树的递归和非递归解法
【刷算法】翻转二叉树的递归和非递归解法
【刷算法】翻转二叉树的递归和非递归解法
|
存储 算法 C#
【查找算法】二分查找(C# + 递归、非递归和变种形式)
本文主要介绍二分查找算法,通过图片解析每一次查找的情况。代码通过C#实现,分别有递归、非递归和变种三种形式。其中变种主要**解决数组出现重复数据**的问题。最后,我们还分析了二分查找的局限性。
|
算法
【刷算法】判断二叉搜索树的后序遍历序列的递归实现和非递归实现
【刷算法】判断二叉搜索树的后序遍历序列的递归实现和非递归实现
117 0
|
算法
【刷算法】翻转单链表的递归和非递归方法
【刷算法】翻转单链表的递归和非递归方法
|
算法
【刷算法】求二叉树深度的递归以及非递归解法
【刷算法】求二叉树深度的递归以及非递归解法