浅浅梳理一下双轴快排(DualPivotQuickSort)

2023-10-22 17:30

本文主要是介绍浅浅梳理一下双轴快排(DualPivotQuickSort),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原理:

双轴嘛,也就是取两个基准pivot1,pivot2,更高效的分拣原数组中的元素。

取两基准分别标记数组两端,然后拿一个变量k对基准之间的元素进行扫描。通过一定的交换使当前区域分为X < pivot1,pivo1 <= X <= pivot2,pivot2 < X 三部分。

ik         ......         j
X < pivot1ipivo1 <= X <= pivot2k......jX>pivot2

之后再将三区域分别递归即可

由于k向后扫描,设置函数成立条件(k < j)比较好。这样的话应该优先处理区域前半部分的数据

演示:

用数组[2, 1, 3, 4, 7, 0, 5, 9, 6, 8]为例过一遍:

初始状态,基准分别为2, 8

第①次,1属于第1区间,同时也呆在第1区间,不管它~ i,k继续前进
[2, 1, 3, 4, 7, 0, 5, 9, 6, 8]

  i   k                              j
第②次:3 > 2,i 停下等待k找到一个乱跑的第1区间成员把3这个第2区间成员换掉,k独自前进

[2, 1, 3, 4, 7, 0, 5, 9, 6, 8]

      i  k                           j

第③次:k独自前进中...

[2, 1, 3, 4, 7, 0, 5, 9, 6, 8]

      i      k                       j

第④次:k独自前进中.>_<.

[2, 1, 3, 4, 7, 0, 5, 9, 6, 8]

      i          k                   j

第⑤次:k遇到了0,0 < 2,i先向前一步标记到k离开的地方...而后与k将标记的数交换,k继续前进

[2, 1, 0, 4, 7, 3, 5, 9, 6, 8]

         i               k           j

第⑥次:k独自前进...

[2, 1, 0, 4, 7, 3, 5, 9, 6, 8]

         i               k           j

第⑦次:k遇到了9!9 > 8。k告诉j赶紧找到一个不该在第3区间呆着的数,j急忙搭上while,回头便遇到了老6...j便把6踢给了k,和9换了位置。k得到6后判断了一下,这不是第1区间的元素,便让i继续原地待命

[2, 1, 0, 4, 7, 3, 5, 6, 9, 8]

          i                  k   j 

第⑧次:k继续前进,k,j相遇了,它们之间没有未扫描过的元素了。分区结束。i和j此时站的位置是3区间的两个交界处,也即两基准要放的位置。于是将左基准与i位置的数交换,右基准与j位置的数交换,第一次对数据的分拣便完成了

[0, 1, 2, 4, 7, 3, 5, 6, 8, 9]

          i                      kj 

第一次分拣完后:

[0, 1, 2, 4, 7, 3, 5, 6, 8, 9](红色是基准)

输出如下:

6adc4d1a6a324a16b7a377876443519d.png

代码:

Main类:

package SeachAndFindTest;
import java.util.*;
/*Main类
*/
public class Main {private static final Scanner sc = new Scanner(System.in);private static void timeCost(long begin, long end){System.out.println("\n用时: " + (end - begin) + "ms\n");}private static int[] makeRandomArr(int size, int left, int right){int[] arr = new int[size];for(int i = 0; i < size; i++){arr[i] = (int)(Math.random()*(right - left + 1) + left);}return arr;}private static int[] getRandomArr(int[] arr, int size){return Arrays.copyOf(arr, size);}private static void printArr(int[] arr){System.out.println(Arrays.toString(arr));}public static void main(String[] args) {System.out.print("""请输入期望的数组长度,数据范围。例:期望数组长度为10,数据范围[0,10],则输入:10 0 10请输入:\s""");int size = sc.nextInt(), left = sc.nextInt(), right = sc.nextInt();if(size <= 0 || left < 0 || left > right){System.out.println("不是有效数据!");return;}double flag = (double)(right - left + 1) / size;if(flag < 0.33){System.out.println("\n您当前测试的数据将有高重复度的特征,相关算法耗时会有不同\n");}else{System.out.println("\n您当前测试的数据将有低重复度的特征,相关算法耗时会有不同\n");}int[] basicArr = makeRandomArr(size, left, right);int[] arr = getRandomArr(basicArr, size);System.out.println("当前数组长度:" + arr.length + "; 数据范围:[" + left + "," + right + "];");boolean t = false;if(size <= 10000){t = true;System.out.println("数组: ");printArr(arr);}else{System.out.println("当前数组长度大于10000,是否展示?请输入 是/否:");String rubbish = sc.next();String ans = sc.nextLine();if(Objects.equals(ans, "是")){t = true;System.out.println("数组: ");printArr(arr);}}long begin = System.currentTimeMillis();AllKindQuickSort.DualPivotQuickSort.sort(arr);long end = System.currentTimeMillis();if(t){System.out.println("有序数组:");printArr(arr);}timeCost(begin, end);sc.close();}
}

DualPivotQuickSort类部分:

//双轴快排
public static class DualPivotQuickSort{public static void sort(int[] arr) {dualPivotQuickSort(arr, 0, arr.length - 1);}private static void dualPivotQuickSort(int[] arr, int left, int right) {if (left < right) {if (arr[left] > arr[right]) {//升序排序,先调整两基准顺序swap(arr, left, right);}int pivot1 = arr[left], pivot2 = arr[right];int i = left, j = right, k = left + 1;level_one: while (k < j) {//先判断k标记的数是否属于第一区间,如果是的话,i向前//一位到达第二区间首,然后i,k标记的数进行交换,扩展//第一区间同时第二区间后移,其他区间关系类似if (arr[k] < pivot1) {swap(arr, ++i, k++);}//下面再尝试用k,j寻找两个不在正确区间的数else if (arr[k] <= pivot2) {//在第二区间找一个//由于要不断搬运第一区间的数(第一个if),这里不//能用while,必须一步一步找k++;}else {//在第三区间找一个while (arr[--j] > pivot2) {//如果找完了都符合,那么这次分区结束,退出循环if (j <= k) {break level_one;}}//找到两个不合法的值后,交换他们swap(arr, j, k);//再判断需不需要继续向前调整if (arr[k] < pivot1) {swap(arr, ++i, k);}//k后移,等待继续比较k++;}}//分区完成后,将两基准值放到正确位置swap(arr, left, i);swap(arr, right, j);//再分别对三个区间递归处理dualPivotQuickSort(arr, left, i - 1);dualPivotQuickSort(arr, i + 1, j - 1);dualPivotQuickSort(arr, j + 1, right);}}
}

输出:

04206600a11e40b5aec926df6fd82fbf.png

这篇关于浅浅梳理一下双轴快排(DualPivotQuickSort)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/262688

相关文章

梳理2024年,螺丝钉们爱用的3款剪辑软件

这年头,视频到处都是,就跟天上的星星一样数不清。不管你是公司里的新面孔,还是职场上的老狐狸,学会怎么剪视频,就好比找到了赢的秘诀。不管是给上司汇报工作,展示你的产品,还是自己搞点小视频记录生活,只要是剪辑得漂亮,肯定能一下子吸引大家的目光,让人记得你。咱们今天就来侃侃现在超火的三款视频剪辑工具,尤其是PR剪辑,你肯定听说过,这货在剪辑界可是大名鼎鼎,用它剪视频,既专业又麻利。 NO1. 福昕轻松

【详细介绍一下GEE】

GEE(Google Earth Engine)是一个强大的云计算平台,它允许用户处理和分析大规模的地球科学数据集,如卫星图像、气候模型输出等。以下是对GEE用法的详细介绍: 一、平台访问与账户设置 访问GEE平台: 用户可以通过访问Google Earth Engine的官方网站来开始使用GEE。 创建账户: 用户需要注册并登录Google账户,然后申请访问GEE平台。申请过程可能需要提

快排Java

快速排序的复杂度 快排代码 package leetcode;import java.util.Arrays;public class QuickSort {public static void quickSort(int[] array, int low, int high) {if (low < high) {int pivotIndex = partition(array, low,

stl的sort和手写快排的运行效率哪个比较高?

STL的sort必然要比你自己写的快排要快,因为你自己手写一个这么复杂的sort,那就太闲了。STL的sort是尽量让复杂度维持在O(N log N)的,因此就有了各种的Hybrid sort algorithm。 题主你提到的先quicksort到一定深度之后就转为heapsort,这种是introsort。 每种STL实现使用的算法各有不同,GNU Standard C++ Lib

C语言程序设计 笔记代码梳理 重制版

前言 本篇以笔记为主的C语言详解,全篇一共十章内容,会持续更新基础内容,争取做到更详细。多一句没有,少一句不行!  形而上学者谓之道,形而下学者谓之器 形而上学者谓之道,形而下学者谓之器 第1章 C语言的流程 1.C程序经历的六个阶段 编辑(Edit)预处理(Preprocess)编译(Compile)汇编(Assemble)链接(Link)执行(Execute)  2.

0906作业+思维导图梳理

一、作业: 1、创捷一个类似于qq登录的界面 1)源代码 #include "widget.h"#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget){ui->setupUi(this);//QPushbutton:登录、退出this->join = new QP

做技术的大家可以看一下这些网站,

1   csdn  http://www.csdn.net/ 2. 开源中国  http://www.oschina.net/ 3. 深度开源(有些经验之谈) http://www.open-open.com/ 上面很多东西大家可以学很多。。。。。。 android须知的网址 Android开发者网站可以很好的帮助你,很多的文档也可以通过SDK工具下载。这些文档不仅仅是Javadoc A

简单梳理UE4的Houdini官方插件代码

前言 Houdini官方插件名字叫 “Houdini Engine”,它搭建了Houdini数据与UE4数据间的桥梁。我接触这个插件已经有段时间了,我想是时候梳理一下插件的结构了。(当前我用的UE4版本是4.24.2,Houdini版本18.0.348) 需要说明的是,这篇博客主要是从代码出发的。我准备先分析插件整体的代码结构,再逐个翻阅每个文件试图搞明白他角色。但如果不准备研究代码结构和实现

梳理轻量级建模软件Silo中的所有操作(2):修改

前言 修改(Modify)类操作是建模时使用最为频繁的操作,因此几乎每个操作都分配了快捷键。 本篇包含的快捷键有27个: 操作快捷键追加面(P)追加边(Shift+E)倒角(B)布尔减(,)布尔合(Ctrl+,)布尔交(Shift+<)分离(Ctrl+B)桥接(Shift+B)割裂(X)挤出(Z)补洞(Shift+F)拍扁(Alt+Shift+F)插入型缩放(I)局部缩放(Ctrl+E)局部

大数据开发体系,进来了解一下?

“5G失败、物联网已死、鼓吹大数据无用论”打开手机又是承接今日份的“丧”, 这种丧味十足的帖子我们已经被投喂得太多了 ,还是原来的配方,还是熟悉的味道,说这些话的人,多少显得无聊而耸人听闻。 有这样一句话叫数据重构商业,流量改变未来。不管怎么唱衰,大数据时代已经向我们滚滚而来,早已成为现代社会不可缺少的一部分。 “不参与大数据建设,10年后一定后悔”。 早在几年前,马云就在某次