我的编程空间,编程开发者的网络收藏夹
学习永远不晚

详解Java双轴快速排序算法

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

详解Java双轴快速排序算法

一、前言

首选,双轴快排也是一种快排的优化方案,在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个,划分的区间由原来的两个变成三个,最坏最坏的情况就是左右同大小并且都是最大或者最小,但这样的概率相比一个最大或者最小还是低很多很多,所以双轴快排的优化力度还是挺大的。

3.1、总体情况分析

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

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

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

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

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

3.2、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++即可

3.3、收尾工作

在执行完这一趟即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)大于pivot2
        int 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;
    }
}

执行结果为:

以上就是详解Java双轴快速排序算法的详细内容,更多关于Java 双轴快速排序算法的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

详解Java双轴快速排序算法

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

快速掌握java排序算法-快速排序(图文)

概念快速排序属于交换排序,主要步骤是使用基准元素进行比较,把小于基准元素的移动到一边,大于基准元素的移动到另一边。从而把数组分成两部分,然后再从这两部分中选取出基准元素,重复上面的步骤。过程如下:(推荐视频:java视频教程) 紫色:基准元素绿色:大于基准元
快速掌握java排序算法-快速排序(图文)
2017-05-20

FlutterDart快速排序算法示例详解

这篇文章主要为大家介绍了FlutterDart快速排序算法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-12-09

java数据结构与算法之快速排序详解

本文实例讲述了java数据结构与算法之快速排序。分享给大家供大家参考,具体如下:交换类排序的另一个方法,即快速排序。快速排序:改变了冒泡排序中一次交换仅能消除一个逆序的局限性,是冒泡排序的一种改进;实现了一次交换可消除多个逆序。通过一趟排序
2023-05-31

排序算法图解之Java快速排序的分步刨析

快速排序是通过一趟排序将要排序的数据分割为独立的两个部分,一部分的所有数据比另外一部分的所有数据要小,然后按照此方法对这两部分分别进行快速排序,整个过程可以递归进行,以此达到整个数据变成有序序列。本文通过示例讲解了快速排序的实现,需要的可以参考一下
2022-11-13

java如何实现快速排序算法

这篇文章将为大家详细讲解有关java如何实现快速排序算法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。快速排序算法使用的分治法策略来把一个序列分为两个子序列来实现排序的思路:1.从数列中挑出一个元素,称为
2023-06-02

Java排序算法怎么快速上手

本篇内容主要讲解“Java排序算法怎么快速上手”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java排序算法怎么快速上手”吧!插入排序插入排序的基本思想:每步将一个待排序元素,按其排序码大小插入
2023-06-27

Java 归并排序算法、堆排序算法实例详解

基本思想:  归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。归并排序示例:合并方法:设r[i…n]由两个有序子表r[i…m
2023-05-31

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录