40分钟掌握快速排序-三路快排算法

Posted 栗子~~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了40分钟掌握快速排序-三路快排算法相关的知识,希望对你有一定的参考价值。

前言

  如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
  而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!


40分钟掌握快速排序-三路快排算法

01 三路快排概念:

 从数组中随机找一个基准值(piovt),移动数组中的元素进行分区,将小于基准值的元素移动至左分区,将等于基准值的元素移动至中间分区,将大于基准值的元素移动至右分区。分区完成后对左、右分区的元素分别进行快排。


02 快速排序-三路快排设计:

在这里插入图片描述

02::01 快速排序-三路快排涉及基本元素:

arr : 数组
index: 数组位置索引
p: 基准值(数值)
lt: <基准值所处位置索引
rt: >基准值所处位置索引
l: 数组首位置
r: 数据尾位置


02::02 三个分区范围定义:

左分区:[l+1 ,lt]
中分区:[lt+1,index-1]
右分区:[gt,r]

注:排序刚开始时需要确定边界,index的开始索引指向l+1,lt的初始值l,而gt的初始值是则是r+1。


02::03 设计:

data{
lt; <基准值所处位置索引
rt; >基准值所处位置索引
}
递归函数(arr,l,r){
/**
* 分区逻辑:
* 1、以arr[l]为基准数值
* 2、遍历索引l+1 、退出条件 l+1 < r+1
* 3、当l+1 = r+1 交换基准值 l处元素与lt处元素
*/
data = 分区(arr,l,r-1);
//和小于基准值区间的元素在进行三路快排
递归函数(arr,l,data.lt);
//和大于基准值区间的元素在进行三路快排
递归函数(arr,data.rt,r);
}


03 实战:

废话不多说,放我的练习demo源码,运行走起来(上面注释写的蛮全的):

package com.yzy.demo.javatest.quicksort;

import com.alibaba.fastjson.JSON;

import java.util.Random;

/**
 * 快速排序-三路快排
 * @author yangzhenyu
 * */
class QuickData{
    //<基准值所处位置索引
    private int lt;
    //>基准值所处位置索引
    private int rt;

    public QuickData(int lt, int rt) {
        this.lt = lt;
        this.rt = rt;
    }
    public int getLt() {
        return lt;
    }
    public int getRt() {
        return rt;
    }

}
public class QuickSort {

    /**
     * 获取一个区间的随机数
     *
     * @param min 最小
     * @param max 最大
     * @return 返回一个随机数
     * @author yangzhenyu
     */
    public static int nextInt(int min, int max) {
        return new Random().nextInt(max - min) + min;
    }
    /**
     * 创建测试数据
     * */
    public static int [] createTestData(int num){
        int [] data = new int[num];
        for (int i = 0;i<num;i++){
            data[i] = nextInt(0,10000);
        }
        return data;
    }
    /**
     * 分区
     * @param arr 被排序的数组
     * @param l 起始位置
     * @param r 末尾位置
     * @return QuickData 分区索引位置
     * @author yangzhenyu
     * */
    public static  QuickData partition(int [] arr, int l, int r){
        // 基准值为数组的零号元素
        int p = arr[l];
        // 左区间的初始值: L
        int lt = l;
        // 右区间的初始值: R+1
        int gt = r + 1;
        for (int index= l + 1; index < gt;){
            if(arr[index] == p){
                // 当前index指向的元素等于p
                index++;
            } else if(arr[index] > p){
                // 当前index指向的元素大于p,将gt-1处的元素与当前索引处的元素交换位置,gt--
                int tem = arr[index];
                arr[index] = arr[gt-1];
                arr[gt-1] = tem;
                gt--;
            }else{
                // 当前i指向的元素小于p,将lt+1处的元素与当前索引处的元素交换位置,lt+1,i+1
                int tem = arr[index];
                arr[index] = arr[lt+1];
                arr[lt+1] = tem;
                lt++;
                index++;
            }
        }
        // i走向gt处,除了基准值外的元素,其余的空间已经分区完毕,交换基准值与lt处的元素,lt-1,最终得到我们需要的三个区间
        int tem = arr[l];
        arr[l] = arr[lt];
        arr[lt] = tem;
        lt--;
        System.out.println(String.format("三路快排后的数组:%s,lt:【%d】,rt:【%d】",JSON.toJSONString(arr),lt,gt));
        return new QuickData(lt,gt);
    }

    /**
     * 快速排序-三路快排
     * @param arr 被排序的数组
     * @param l 起始位置
     * @param r 末尾位置
     * @author yangzhenyu
     * */
    public static void quickSort(int[] arr, int l, int r){
        if(l >= r){
            return;
        }
        QuickData obj = partition(arr, l, r);
        // 递归执行: 将没有大于p,和小于p区间的元素在进行三路快排
        quickSort(arr,l,obj.getLt());
        quickSort(arr,obj.getRt(),r);
    }
    public static void main(String[] args) {
        //01 创建测试数据
        int[] testData = createTestData(17);
        System.out.printf("快速排序前的数组:%s\\n",JSON.toJSONString(testData));
        //02 快速排序-三路快排
        quickSort(testData,0,testData.length-1);
        //03 快速排序后的结果
        System.out.printf("快速排序后的数组:%s\\n",JSON.toJSONString(testData));
    }
}

运行:

在这里插入图片描述

以上是关于40分钟掌握快速排序-三路快排算法的主要内容,如果未能解决你的问题,请参考以下文章

高级排序算法实现与优化

快速排序思路整理

快排模板

高级排序算法之三路快速排序

三路快排,堆排序

三路快速排序算法