原创公众号:「bigsai」,转载需注明出处
关注回复bigsai领取Java进阶pdf,回复进群加入力扣打卡群(目前200+).
觉得不错还请一键三连

前言

在排序算法中,快排是占比非常多的一环,但是快排其思想一直被考察研究,也有很多的优化方案。这里主要讲解双轴快排的思想和实现。

首选,双轴快排也是一种快排的优化方案,在JDK的Arrays.sort()中被主要使用。所以,掌握快排已经不能够满足我们的需求,我们还要学会双轴快排的原理和实现才行。

回顾单轴快排

单轴快排也就是我们常说的普通快速排序,对于快速排序我想大家应该都很熟悉:基于递归和分治的,时间复杂度最坏而O(n2),最好和平均情况为O(nlogn).

而快排的具体思路也很简单,每次在待排序序列中找一个数(通常最左侧多一点),然后在这个序列中将比他小的放它左侧,比它大的放它右侧。

如果运气肯不好遇到O(n)平方的,那确实就很被啦:

实现起来也很容易,这里直接贴代码啦:

private static void quicksort(int [] a,int left,int right)
{int low=left;int high=right;//下面两句的顺序一定不能混,否则会产生数组越界!!!very important!!!if(low>high)//作为判断是否截止条件return;int k=a[low];//额外空间k,取最左侧的一个作为衡量,最后要求左侧都比它小,右侧都比它大。while(low<high)//这一轮要求把左侧小于a[low],右侧大于a[low]。{while(low<high&&a[high]>=k)//右侧找到第一个小于k的停止{high--;}//这样就找到第一个比它小的了a[low]=a[high];//放到low位置while(low<high&&a[low]<=k)//在low往右找到第一个大于k的,放到右侧a[high]位置{low++;}a[high]=a[low];         }a[low]=k;//赋值然后左右递归分治求之quicksort(a, left, low-1);quicksort(a, low+1, right);
}

双轴快排分析

咱们今天的主题是双轴快排,双轴和单轴的区别你也可以知道,多一个轴,前面讲了快排很多时候选最左侧元素以这个元素为轴将数据划分为两个区域,递归分治的去进行排序。但单轴很多时候可能会遇到较差的情况就是当前元素可能是最大的或者最小的,这样子元素就没有被划分区间,快排的递推T(n)=T(n-1)+O(n)从而为O(n2).

双轴就是选取两个主元素理想将区间划为3部分,这样不仅每次能够确定元素个数增多为2个,划分的区间由原来的两个变成三个,最坏最坏的情况就是左右同大小并且都是最大或者最小,但这样的概率相比一个最大或者最小还是低很多很多,所以双轴快排的优化力度还是挺大的。

总体情况分析

至于双轴快排具体是如何工作的呢?其实也不难理解,这里通过一系列图讲解双轴快排的执行流程。

首先在初始的情况我们是选取待排序区间内最左侧、最右侧的两个数值作为pivot1pivot2 .作为两个轴的存在。同时我们会提前处理数组最左侧和最右侧的数据会比较将最小的放在左侧。所以pivot1<pivot2.

而当前这一轮的最终目标是,比privot1小的在privot1左侧,比privot2大的在privot2右侧,在privot1和privot2之间的在中间。

这样进行一次后递归的进行下一次双轴快排,一直到结束,但是在这个执行过程应该去如何处理分析呢?需要几个参数呢?

  • 假设知道排序区间[start,end]。数组为arr,pivot1=arr[start],pivot2=arr[end]
  • 还需要三个参数left,right和k。
  • left初始为start,[start,left]区域即为小于等于pivot1小的区域(第一个等于)。
  • right与left对应,初始为end,[right,end]为大于等于pivot2的区域(最后一个等于)。
  • k初始为start+1,是一个从左往右遍历的指针,遍历的数值与pivot1,pivot2比较进行适当交换,当k>=right即可停止。

k交换过程

然后你可能会问k遍历时候究竟怎么去交换?left和right该如何处理呢?不急我带你慢慢分析,首先K是在left和right中间的,遍历k的位置和pivot1,pivot2进行比较:

如果arr[k]<pivot1,那么先++left,然后swap(arr,k,left), 因为初始在start在这个过程不结束start先不动。 然后k++;继续进行

而如果arr[k]>pivot2.(区间自行安排即可)有点区别的就是right可能连续的大于arr[k],比如9 3 3 9 7如果我们需要跳过7前面9到3才能正常交换,这和快排的交换思想一致,当然再具体的实现上就是right–到一个合适比arr[k]小的位置。然后swap(arr,k,right)切记此时k不能自加。 因为带交换的那个有可能比pivot1还小要和left交换。

如果是介于两者之间,k++即可

收尾工作

在执行完这一趟即k=right之后,即开始需要将pivot1和pivot2的数值进行交换

swap(arr, start, left);
swap(arr, end, right);

然后三个区间根据编号递归执行排序函数即可。

双轴快排代码

在这里,分享下个人实现双轴快排的代码:

import java.util.Arrays;public class 双轴快排 {public static void main(String[] args) {int a[]= {7,3,5,4,8,5,6,55,4,333,44,7,885,23,6,44};dualPivotQuickSort(a,0,a.length-1);System.out.println(Arrays.toString(a));}private static void dualPivotQuickSort(int[] arr, int start, int end) {if(start>end)return;//参数不对直接返回if(arr[start]>arr[end])swap(arr, start, end);int pivot1=arr[start],pivot2=arr[end];//储存最左侧和最右侧的值//(start,left]:左侧小于等于pivot1 [right,end)大于pivot2int left=start,right=end,k=left+1;while (k<right) {//和左侧交换if(arr[k]<pivot1){//需要交换swap(arr, ++left, k++);}else if (arr[k]<=pivot2) {//在中间的情况k++;}else {while (arr[right]>pivot2) {//如果全部小于直接跳出外层循环if(right--==k)break ;}if(k>=right)break ;swap(arr, k, right);}}swap(arr, start, left);swap(arr, end, right);dualPivotQuickSort(arr, start, left-1);dualPivotQuickSort(arr, left+1, right-1);dualPivotQuickSort(arr, right+1, end);}static void swap(int arr[],int i,int j){int team=arr[i];arr[i]=arr[j];arr[j]=team;}
}

执行结果为:

好啦,到这里双轴快排就实现完成啦。至于算法分析,希望在评论区和你们讨论哦!希望各位动动小手给个一键三连哦!

原创不易,欢迎关注「bigsai」回复bigsai领取Java进阶资料:

【排序算法】——图解双轴快排(建议收藏)相关推荐

  1. 浅谈Java底层排序双轴快排

    在Java 底层的排序中有几个非常有用并且面试可以装逼的算法,TimSort,DualPivotQuicksort( 双轴快速排序 ),( binarySort)二分插入排序. 这三个排序,TimSo ...

  2. Java 细节汇总(4)-Arrays 中的双轴快排

    文章目录 1. Arrays 中的双轴快排 2. Java 中 switch 支持字符串的原理 3. Java 中 break,continue 标签的用法 4. Java 中 Math.ceil() ...

  3. 单轴快排(SinglePivotQuickSort)和双轴快排(DualPivotQuickSort)及其JAVA实现

    快速排序使用的是分治思想,将原问题分成若干个子问题进行递归解决.通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快 ...

  4. 八大排序算法之快速排序(下篇)(快排的优化+非递归快排的实现)

    目录 一.前言 1.快速排序的实现: 快速排序的单趟排序(排升序)(快慢指针法实现):​ 2.未经优化的快排的缺陷 二.快速排序的优化 1.三数取中优化 优化思路: 2. 小区间插入排序优化 小区间插 ...

  5. (十)更快的排序算法(归并、快排、基数)

    目标 1) 使用下列方法将一个数组按升序排序:归并排序.快速排序和基数排序 2) 评估排序的效率,讨论不同的方法的相对效率 目录 9.1 归并排序 9.1.1 归并数组 9.1.2 递归归并排序 9. ...

  6. 排序算法:冒泡和快排 摘自网络

    冒泡排序: 首先我们自己来设计一下"冒泡排序",这种排序很现实的例子就是: 我抓一把沙仍进水里,那么沙子会立马沉入水底, 沙子上的灰尘会因为惯性暂时沉入水底,但是又会立马像气泡一样 ...

  7. 八大排序算法总结Java代码实现(建议收藏后食用)

    目录 排序算法介绍 相关术语 排序的稳定性 排序分类 内排序与外排序 算法时间复杂度 度量一个程序(算法)执行时间的两种方法 时间频度 忽略常数项 忽略低次项 忽略系数 时间复杂度 常数阶O(1) 对 ...

  8. C语言排序算法 选择排序 插入排序 快速排序 qsort实现快排 堆排序

    常见排序算法 选择排序 选择排序(Selection sort)是一种简单直观的排序算法. 它的工作原理如下. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素 ...

  9. 三路快排算法加强版(三路快排的再次改进)

    :不要忘记初心哈 :) 理论依据 快排算法的缺陷及其逐一改进 三路快排尽可能三等份划分区间 通过待排元素的区间长度划分? 通过待排元素的最值之差划分? 直接使用待排元素的最大值划分? 实验数据 大范围 ...

最新文章

  1. 跟我学jQuery(三) 无所不能的选择器1
  2. 皮一皮:论一件艺术品的诞生...
  3. python编程实例详解-Python编程之列表操作实例详解【创建、使用、更新、删除】...
  4. 关于【C++项目:无法解析的外部符号】
  5. 【Python】Jupyter Notebook的十大隐藏技巧--如何大大加速算法的迭代
  6. Xquery 被设计用来查询 XML 数据
  7. Css基本语法及页面引用
  8. c# 计算空格宽度像素_用pythonnet为计算机视觉做图像整理
  9. Mybatis构建sql语法
  10. 【JVM系列】一步步解析java执行内幕,java初级面试笔试题
  11. 关于Debug.exe
  12. LCN(使用springCloud)分布式事物原理
  13. 扫地阿姨看完都学会了!写给即将正在找工作的Java攻城狮,砥砺前行!
  14. Vue3 源码阅读(3):响应式系统 —— 重置 effect 的依赖收集、嵌套的 effect、effect 调度执行
  15. Object.keys方法
  16. incsgo 可直接取回最好的国内CSGO饰品皮肤开箱网站
  17. 多旋翼无人机组合导航系统-多源信息融合算法附Matlab代码
  18. 【机器学习】P20 模型的诊断 - 验证集
  19. weblogic密码破解
  20. Curl转python在线工具

热门文章

  1. 智能合约重构社会契约(8)以太坊分片
  2. 《研磨设计模式》chap21 解释器模式Interpreter(1)模式介绍
  3. 现代密码学1.2--Kerckhoffs原则
  4. 数学建模——ARIMA时间序列预测模型Python代码
  5. [ATF]-ATF的代码学习篇-一篇就够了
  6. ngrok服务器搭建
  7. 将JPG文件作为EXE执行
  8. 16、Java Swing JProgressBar:进度条组件
  9. 2、创建视图(CREATE VIEW)
  10. 牛客竞赛语法入门班数组栈、队列和stl习题【未完成】