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分钟掌握快速排序-三路快排算法的主要内容,如果未能解决你的问题,请参考以下文章