快速排序(Java分治法)

news2024/11/18 4:47:03

快速排序(Java分治法)

文章目录

  • 快速排序(Java分治法)
    • 0、 分治策略
    • 1、思路步骤
    • 2、代码
    • 3、复杂度分析
      • 3.1 最好情况
      • 3.2 最坏情况
      • 3.3 平均情况
      • 3.4 性能影响因素
    • 4、合并排序VS快速排序
    • 5、参考


在这里插入图片描述


0、 分治策略

快速排序是对气泡排序的一种改进方法,它是由C.A.R. Hoare于1962年提出的

快速排序的分治策略

  • 划分:选定一个记录作为轴值,以轴值为基准将整个序列划分为两个子序列r1 … ri-1和ri+1 … rn,前一个子序列中记录的值均小于或等于轴值,后一个子序列中记录的值均大于或等于轴值;

  • 求解子问题:分别对划分后的每一个子序列递归处理;

  • 合并:由于对子序列r1 … ri-1和ri+1 … rn的排序是就地进行的,所以合并不需要执行任何操作。

tp

  • 合并排序按照记录在序列中的位置对序列进行划分
  • 快速排序按照记录的值对序列进行划分

1、思路步骤

以第一个记录作为轴值,对待排序序列进行划分的过程为:

  • 初始化:取第一个记录作为基准,设置两个参数i,j分别用来指示将要与基准记录进行比较的左侧记录位置和右侧记录位置,也就是本次划分的区间;

  • 右侧扫描过程:将基准记录与j指向的记录进行比较,如果j指向记录的关键码大,则j前移一个记录位置。重复右侧扫描过程,直到右侧的记录小(即反序),若i<j,则将基准记录与j指向的记录进行交换;

  • 左侧扫描过程:将基准记录与i指向的记录进行比较,如果i指向记录的关键码小,则i后移一个记录位置。重复左侧扫描过程,直到左侧的记录大(即反序),若i<j,则将基准记录与i指向的记录交换;

  • 重复(2)(3)步,直到i与j指向同一位置,即基准记录最终的位置。

2、代码

private static void qSort(int p, int r) {
    if (p<r) {
      int q = partition(p,r); // 以a[p]为基准元素将a[p:r]划分成3段a[p:q-1],a[q]和a[q+1:r],使得a[p:q-1]中任何元素小于等于a[q],a[q+1:r]中任何元素大于等于a[q]。下标q在划分过程中确定。
      qSort (p,q-1); //对左半段排序
      qSort (q+1,r); //对右半段排序
      }
 }
 private static int partition (int p, int r) {
    int i = p,  //设置数组第一个下标,这样循环访问从第二个元素开始
        j = r + 1;  //设置下表为长度加1,循环访问从最后一个元素开始
    Comparable x = a[p];
    // 将>= x的元素交换到左边区域
    // 将<= x的元素交换到右边区域
    while (true) {
      while (a[++i].compareTo(x) < 0);
      while (a[--j].compareTo(x) > 0);
      if (i >= j) break;  //I,j游标会合时退出循环
      MyMath.swap(a, i, j);
    } 
    a[p] = a[j];
    a[j] = x;
    return j;  交换位置并返回分割点位置
 }

在快速排序中,记录的比较和交换是从两端向中间进行的,关键字较大的记录一次就能交换到后面单元,关键字较小的记录一次就能交换到前面单元,记录每次移动的距离较大,因而总的比较和移动次数较少。

tp

3、复杂度分析

3.1 最好情况

最好情况下,每次划分对一个记录定位后,该记录的左侧子序列与右侧子序列的长度相同。在具有n个记录的序列中,一次划分需要对整个待划分序列扫描一遍,则所需时间为O(n)。设T(n)是对n个记录的序列进行排序的时间,每次划分后,正好把待划分区间划分为长度相等的两个子序列,则有:

T(n)≤2 T(n/2)+n
      ≤2(2T(n/4)+n/2)+n=4T(n/4)+2n
      ≤4(2T(n/8)+n/4)+2n=8T(n/8)+3n
      … … … 
      ≤nT(1)+nlog2n=O(nlog2n) 

因此,时间复杂度为O(nlog2n)。

注意这个n是指划分所用的时间复杂度而不是合并的时间复杂度

3.2 最坏情况

最坏情况下,待排序记录序列正序或逆序,每次划分只得到一个比上一次划分少一个记录的子序列(另一个子序列为空)。此时,必须经过n-1次递归调用才能把所有记录定位,而且第i趟划分需要经过n-i次关键码的比较才能找到第i个记录的基准位置,因此,总的比较次数为:

tp

因此,时间复杂度为O(n2)。

3.3 平均情况

我们假设平均情况下,每次分区之后,两个分区的大小比例为 1:k。当 k =9 时,如果用递推公式的方法来求解时间复杂度的话,递推公式就写成 T(n) = T(n/10) + T(9n/10) + n。

tp

快速排序的过程上,每次分区都要遍历待分区区间的所有数据,所以,每一层分区操作所遍历的数据的个数之和就是n。我们现在只要求出递归的高度h,这个快排过程遍历的个数就是 hn ,也就是说,时间复杂度就是O(hn)。

递归树不是满二叉树。这样一个递归树的高度是多少呢?

快速排序结束的条件就是待排序的小区间,大小为1,也就是说叶子节点的数据规模是1。从根节点n 到叶子节点1,递归树中最短的一个路径是每次都乘以 1/10,最长的路径是每次都乘以9/10。

在这里插入图片描述

根据复杂度大O表示法,对数复杂度的底数不管是多少,我们统一写成logn,所有当大小比例是1:9时,快速排序的时间复杂度仍然是O(nlogn)。当 k = 99时,算出的时间复杂度也一样。

在这里插入图片描述

从根到叶的最长简单路径是n–>(2/3)n–>(2/3)^2n–>…–>1。由于当k = log3/2n时,(2/3)^k*n = 1,因此树高为log3/2n。

平均情况下,设基准记录的关键码第k小(1≤k≤n),则有:
在这里插入图片描述

这是快速排序的平均时间性能,可以用归纳法证明,其数量级也为O(nlog2n)。

3.4 性能影响因素

快速排序算法的性能取决于划分的对称性。通过修改算法partition,可以设计出采用随机选择策略的快速排序算法。在快速排序算法的每一步中,当数组还没有被划分时,可以在a[p:r]中随机选出一个元素作为划分基准,这样可以使划分基准的选择是随机的,从而可以期望划分是较对称的。

private static int randomizedPartition (int p, int r) {
    int i = random(p,r);
    MyMath.swap(a, i, p);
    return partition (p, r);
}
  • 最坏时间复杂度:O(n2)
  • 平均时间复杂度:O(nlogn)
  • 辅助空间:O(n)或O(logn)
  • 稳定性:不稳定

4、合并排序VS快速排序

快排的前身是归并,归并的最大问题是需要额外的存储空间,并且由于合并过程不确定,致使每个元素在序列中的最终位置上不可预知的。针对这一点,快速排序提出了新的思路:把更多的时间用在“分”上,而把较少的时间用在“治”上。从而解决了额外存储空间的问题,并提升了算法效率

v

如何确定这个基准值呢?

  • 随机
    在所要排序的数组中,随机选取一个数来作为基准值,需要将其交换到最边上。

  • 直接取最边上的值(任选左右)。

  • 三数取中法

在[left, left +(right -left)/2, righ ] 中,通过判断,选取其中大小为 中 的元素。

5、参考

  • 算法设计与分析(第4版)

结束!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/125419.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

minio下载、安装、Java集成应用

1.下载MinIO 下载链接:https://dl.min.io/server/minio/release/windows-amd64/minio.exe 网盘:https://pan.baidu.com/s/1uS2ii958tTjnb0KTpsKpCg 提取码:3nr9 2.安装启动 下载好的文件不要双击,自己定义一个文件夹放下载好的文件,本文指定的位置D:\minio,同时创建一…

淮北绿金通过港交所上市聆讯:净利润再度下滑,收入依赖股东

12月27日&#xff0c;港交所披露的信息显示&#xff0c;淮北绿金产业投资股份有限公司&#xff08;下称“淮北绿金”&#xff09;通过港交所上市聆讯并递交了聆讯后招股书&#xff0c;光大证券国际为其独家保荐人。据了解&#xff0c;淮北绿金曾于2021年12月递表&#xff0c;20…

【答学员问】网站换ip后遇到的问题排查思路

文章目录遇到问题先进行基本的问题排查1. 查看IP2. 是否能通网3. 关闭防火墙和selinux4. 使用windows的浏览器访问问题复现1. 安装好wordpress &#xff0c;确保能够访问2. 修改IP&#xff0c;进行测试3. 访问测试&#xff1a;问题排查问题解决方案遇到问题 学员反馈在家访问网…

C++类和对象1:类是什么?对象是什么?

目录 类的引入 类的定义 类的定义规则 类域问题&#xff1a; 类的访问限定符及封装 访问限定符 封装 类的实例化 类对象的大小问题 this指针 This指针的一些特性&#xff1a; 类的引入 在学习C语言的时候&#xff0c;C语言是面向过程的&#xff0c;关注的是过程&#xff…

2023年5月北京老博会,医养家具展,护理床展,老年护理展

2023中国国际养老服务业博览会CISSE介绍&#xff1a; 2023中国国际养老服务业博览会&#xff08;CISSE&#xff09;将于5月5-7日在北京国家会议中心举行。大会以养老产业为主题&#xff0c;通过展贸平台为涉老企业抢占市场先机&#xff0c;对企业营销策略、宣传影响力、定位产品…

apt-fast 使用

apt-fast 使用1. 安装2. 使用默认的apt-get install&#xff0c;有时下载会非常的慢&#xff0c;尤其是安装的一些ppa包的时候。apt-fast 通过使用多线程来给apt提速&#xff0c;极大地提高了效率。 1. 安装 添加ppa仓库 sudo add-apt-repository ppa:apt-fast/stable 更新软…

CAPL学习之路-测试功能集函数(约束和条件)

在test module和test unit中,可以添加事件对象或事件文本作为条件或约束。当事件发生时,条件或约束受损,测试报告中输出“Fail”条目,同时测试用例判定为“Fail” 此类函数有: TestAddCondition/TestAddConstraint,添加事件对象或事件文本作为条件或约束。不管是作为条件…

傻白入门芯片设计,如何写一篇好文章(十八)

目录 一、标题Title 如何看浩如烟海的文献&#xff1f; 二、摘要Abstract 三、介绍Introduction &#xff08;1&#xff09;“六句扩展法” &#xff08;2&#xff09;常见的逻辑&#xff1a; &#xff08;3&#xff09;更好的逻辑&#xff1a; 四、相关工作Related wo…

《CSAPP》笔记——系统级IO、网络编程、并发编程

文章目录传送门系统级IOUnix输入和输出Unix文件Unix文件操作Unix管理打开文件打开文件流程文件共享重定向文件标准IO标准IO流标准IO的缓冲机制RIO&#xff08;Robust IO&#xff09;对比与总结网络编程历史从头构建互联网网络层次以太网段网桥连接的以太网段互联网网络协议互联…

远程代码执行渗透与攻防(一)

目录 前言 远程代码执行&#xff1a;Remote Code Execute 远程命令执行&#xff1a;Remote Command Execute 为什么要远程执行代码&#xff1f; 漏洞危害 近几年影响比较大的RCE漏洞 PHP RCE涉及函数 代码code注入&#xff1a; 命令command注入 &#xff1a; 靶场案…

Word控件Spire.Doc 【评论】教程(4):C#、VB.NET如何在Word的评论中插入图片

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

认真学习MySQL中锁机制(二)

接上文认真学习MySQL中锁机制&#xff08;一&#xff09;我们继续学习MySQL中的锁机制。 【5】按加锁的方式划分&#xff1a;显示锁、隐式锁 ① 隐式锁 一个事务在执行insert操作时&#xff0c;如果即将插入的间隙已经被其他事务加了gap锁&#xff0c;那么本次insert操作会阻…

分类算法KNN的python实现

作者&#xff1a;刘凡 KNN算法介绍 KNN算法是有监督学习中的分类算法&#xff0c;它是一种非参的&#xff0c;惰性的算法模型。非参的意思并不是说这个算法不需要参数&#xff0c;而是意味着这个模型不会对数据做出任何的假设&#xff0c;与之相对的是线性回归&#xff08;我…

隐语任务调度

隐语目前暂定支持的设备列表&#xff1a; 一 PYU 数据所有者是SecretFlow中的PYU设备&#xff0c;明文并成为PYU Objects一个PYU object&#xff08;明文&#xff09;可以被转化为秘密分享&#xff0c;被叫做SPU Object。Python函数可以被发送至SPU设备执行&#xff0c;背后是…

人工智能:图像数字化相关的知识介绍

❤️作者主页&#xff1a;IT技术分享社区 ❤️作者简介&#xff1a;大家好,我是IT技术分享社区的博主&#xff0c;从事C#、Java开发九年&#xff0c;对数据库、C#、Java、前端、运维、电脑技巧等经验丰富。 ❤️个人荣誉&#xff1a; 数据库领域优质创作者&#x1f3c6;&#x…

只从 2022 年算起,谷歌就向社会输送了至少 26 位高端 AI 人才。

2022 年&#xff0c;人工智能在 AIGC、AI for science 等领域持续发展&#xff0c;一些工作也在知识型模型方面做出了探索。除了这些研究成果&#xff0c;我们还会发现这一年人工智能从业者的工作情况也有比较大的变化。 例如&#xff0c;Meta 等大型科技公司进行了大规模的裁…

【 shell 编程 】第1篇 变量

变量 文章目录变量一、前言二、变量1.变量的类型2.变量的运算一、前言 1.什么是 shell 简介&#xff1a; SHELL是UNIX系统的用户与操作系统之间的一种接口。它既是UNIX系统的命令解释程序&#xff0c;又是一种高级的命令程序设计语言。 作为命令解释程序&#xff0c;SHELL接收…

Windows/Mac/Ubuntu环境下安装Dokcer

前提概要&#xff1a; 注意&#xff1a;安装虚拟环境的步骤我放到另外一个文章里面啦&#xff0c;有需要的可以看看哦 Docker介绍&#xff1a;1、Docker 并⾮是⼀个通⽤的容器⼯具&#xff0c;它依赖于已存在并运⾏的 Linux 内核环境。2、Docker 实质上是在已经运⾏的 Linux 下…

智慧养老系统(社区+居家+机构养老)

智慧养老是一个新的养老模式&#xff0c;信息化医疗服务&#xff0c;不仅能够提高养老产业的质量&#xff0c;提高养老成本降低&#xff0c;而且能够提高老人的身体健康&#xff0c;提高养老人的老年生活质量。 智慧养老系统解决方案提供完整的机构养老系统、社区养老系统&…

在项目中使用——newFixedThreadPool线程池

newFixedThreadPool线程池前言newFixedThreadPool的介绍使用newFixedThreadPool的步骤实例化一个固定线程大小线程池创建一个用于启动新线程的类使用submit提交线程最后关闭关闭线程池CountDownLatch配合线程池使用构造CountDownLatch计数器减一使调用该方法的线程处于等待状态…