快速排序 - 递归、非递归实现【十大经典排序算法】

快速排序

一般来说,常用的就是三路快排,左中右主要分为:小于区域 、 等于区域 、 大于区域;每次将数组最右边的数作为基准元素,然后挨个比较,进行排序

在这里插入图片描述

1 递归实现

1.1 定义swap交换函数

将指定位置的两个数值进行互换

private static void swap(int[] arr, int i, int index) {
    int temp = arr[i];
    arr[i] = arr[index];
    arr[index] = temp;
}

1.2 定义partition函数,分出L区、R区;找到等于区域

每次将数组arr划定L点和R点,arr数组一共被分出3个部分

//arr[L..R]范围上,拿arr[R]做划分值
//L...R < = >
public static int[] partition(int[] arr, int L, int R){
    int lessR = L - 1;
    int moreL = R;
    int index = L;
    while(index < moreL){
        if(arr[index] < arr[R]){
            swap(arr, ++lessR, index++);
        } else if(arr[index] > arr[R]){
            swap(arr, --moreL, index);
        } else {
            index++;
        }
    }
    swap(arr, moreL, R);
    return new int[]{ lessR+1, moreL};
}

1.3 找到等于区域之后,又将其重新作为一个整体,重新划分,递归

public static void process(int[] arr, int L, int R){
    if(L >= R){
        return;
    }
    int[] equalsE = partition(arr, L, R);
    process(arr, L, equalsE[0] - 1);
    process(arr, equalsE[1] + 1, R);
}

1.4 定义quickSort调用其他函数

public static void quickSort(int[] arr){
    if(arr == null || arr.length < 2){
        return;
    }
    process(arr, 0, arr.length - 1);
}

1.5 整体代码

public static void quickSort(int[] arr){
    if(arr == null || arr.length < 2){
        return;
    }
    process(arr, 0, arr.length - 1);
}

//arr[L..R]范围上,拿arr[R]做划分值
//L...R < = >
public static int[] partition(int[] arr, int L, int R){
    int lessR = L - 1;
    int moreL = R;
    int index = L;
    while(index < moreL){
        if(arr[index] < arr[R]){
            swap(arr, ++lessR, index++);
        } else if(arr[index] > arr[R]){
            swap(arr, --moreL, index);
        } else {
            index++;
        }
    }
    swap(arr, moreL, R);
    return new int[]{ lessR+1, moreL};
}

public static void process(int[] arr, int L, int R){
    if(L >= R){
        return;
    }
    int[] equalsE = partition(arr, L, R);
    process(arr, L, equalsE[0] - 1);
    process(arr, equalsE[1] + 1, R);
}

private static void swap(int[] arr, int i, int index) {
    int temp = arr[i];
    arr[i] = arr[index];
    arr[index] = temp;
}

2 非递归实现(迭代)

2.1 定义Job内部类,标识L点与R点

//定义内部类Job
public static class Job{
    public int L;
    public int R;
    public Job(int L, int R){
        this.L = L;
        this.R = R;
    }
}

2.2 使用stack结构来存储和消费任务

//非递归方式
public static void quickSort2(int[] arr){
    if(arr == null || arr.length < 2){
        return;
    }
    Stack<Job> stack = new Stack<>();
    stack.push(new Job(0, arr.length - 1));
    while(!stack.isEmpty()){
        Job cur = stack.pop();
        int[] equals = partition(arr, cur.L, cur.R);
        if(equals[0] > cur.L){//有 < 区间
            stack.push(new Job(cur.L, equals[0] - 1));
        }
        if(equals[1] < cur.R){//有 > 区间
            stack.push(new Job(equals[1] + 1, cur.R));
        }
    }
}

2.3 partition函数

//arr[L..R]范围上,拿arr[R]做划分值
//L...R < = >
public static int[] partition(int[] arr, int L, int R){
    int lessR = L - 1;
    int moreL = R;
    int index = L;
    while(index < moreL){
        if(arr[index] < arr[R]){
            swap(arr, ++lessR, index++);
        } else if(arr[index] > arr[R]){
            swap(arr, --moreL, index);
        } else {
            index++;
        }
    }
    swap(arr, moreL, R);
    return new int[]{ lessR+1, moreL};
}

3 定义对数器:验证结果

3.1 构造对数器

随机生成指定范围、指定长度的数组

public static boolean isEquals(int[] arr1, int[] arr2) {
    for (int i = 0; i < arr1.length; i++) {
        if(arr1[i] != arr2[i]){
            return false;
        }
    }
    return true;
}

private static int[] copyArray(int[] arr1) {
    int[] arr2 = new int[arr1.length];
    for (int i = 0; i < arr1.length; i++) {
        arr2[i] = arr1[i];
    }
    return arr2;
}

private static int[] generateRandomArray(int maxSize, int maxValue) {
    int size = (int)(Math.random() * maxSize);
    int value;
    int[] arr = new int[size];
    for (int i = 0; i < size; i++) {
        value = (int)(Math.random() * maxValue);
        arr[i] = value;
    }
    return arr;
}

3.2 整体代码

package com.ali.test;

import java.util.Arrays;
import java.util.Stack;

public class Test06 {
    public static void main(String[] args) {
        int testTime = 500000;
        int maxSize = 100;
        int maxValue = 100;
        System.out.println("测试开始-----");
        for (int i = 0; i < testTime; i++) {
            int[] arr1 = generateRandomArray(maxSize, maxValue);
            int[] arr2 = copyArray(arr1);
            quickSort1(arr1);
            quickSort2(arr2);
            if(!isEquals(arr1, arr2)){
                System.out.println("error....");
                System.out.println(Arrays.toString(arr1));
                System.out.println(Arrays.toString(arr2));
                break;
            }
        }
        System.out.println("测试结束....");
    }

    public static void quickSort1(int[] arr){
        if(arr == null || arr.length < 2){
            return;
        }
        process(arr, 0, arr.length - 1);
    }

    //arr[L..R]范围上,拿arr[R]做划分值
    //L...R < = >
    public static int[] partition(int[] arr, int L, int R){
        int lessR = L - 1;
        int moreL = R;
        int index = L;
        while(index < moreL){
            if(arr[index] < arr[R]){
                swap(arr, ++lessR, index++);
            } else if(arr[index] > arr[R]){
                swap(arr, --moreL, index);
            } else {
                index++;
            }
        }
        swap(arr, moreL, R);
        return new int[]{ lessR+1, moreL};
    }

    public static void process(int[] arr, int L, int R){
        if(L >= R){
            return;
        }
        int[] equalsE = partition(arr, L, R);
        process(arr, L, equalsE[0] - 1);
        process(arr, equalsE[1] + 1, R);
    }

    private static void swap(int[] arr, int i, int index) {
        int temp = arr[i];
        arr[i] = arr[index];
        arr[index] = temp;
    }




    //定义内部类Job
    public static class Job{
        public int L;
        public int R;
        public Job(int L, int R){
            this.L = L;
            this.R = R;
        }
    }
    //非递归方式
    public static void quickSort2(int[] arr){
        if(arr == null || arr.length < 2){
            return;
        }
        Stack<Job> stack = new Stack<>();
        stack.push(new Job(0, arr.length - 1));
        while(!stack.isEmpty()){
            Job cur = stack.pop();
            int[] equals = partition(arr, cur.L, cur.R);
            if(equals[0] > cur.L){//有 < 区间
                stack.push(new Job(cur.L, equals[0] - 1));
            }
            if(equals[1] < cur.R){//有 > 区间
                stack.push(new Job(equals[1] + 1, cur.R));
            }
        }
    }
    //构造对数器
    public static boolean isEquals(int[] arr1, int[] arr2) {
        for (int i = 0; i < arr1.length; i++) {
            if(arr1[i] != arr2[i]){
                return false;
            }
        }
        return true;
    }

    private static int[] copyArray(int[] arr1) {
        int[] arr2 = new int[arr1.length];
        for (int i = 0; i < arr1.length; i++) {
            arr2[i] = arr1[i];
        }
        return arr2;
    }

    private static int[] generateRandomArray(int maxSize, int maxValue) {
        int size = (int)(Math.random() * maxSize);
        int value;
        int[] arr = new int[size];
        for (int i = 0; i < size; i++) {
            value = (int)(Math.random() * maxValue);
            arr[i] = value;
        }
        return arr;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值