【算法】快速排序

算法系列六:快速排序

一、快速排序的递归探寻

1.思路

2.书写

3.搭建

3.1设计过掉不符情况(在最底层时)

3.2查验能实现基础结果(在最底层往上点时)

3.3跳转结果继续往上回搭

4.实质

二、快速排序里的基准排序

1.双路双向交换铺(Hoare法)

1.1原理

1.2实现

1.2.1>=

1.2.2先右再左

2.双路双向覆盖铺(挖坑法)

2.1原理

2.2实现

3.双路单向交换铺(前后指针法)

3.1原理

3.2实现

三、快速排序的复杂度

1.时间复杂度

1.1完全顺序逆序

1.1.1结构影响

1.1.2时间

1.2完全二叉树序

1.2.1结构影响

1.2.2时间

2.空间复杂度

3.优化

3.1三数取中

3.2插入排序

3.2.1栈溢出原因

3.2.2利与弊


一、快速排序的递归探寻

1.思路

左断开结果右断开结果加上突兀根如何实现上一层的结果

左断开有序+右断开有序突兀根实现它比左部分都大、它比右部分都小就可以实现上一层的有序


2.书写

书写时是突兀根先实现再递归实现左右断开结果

书写时反着来先实现突兀根一个节点左边都比都比它小、右边都比它大再用递归实现它断开的左右有序结果


3.搭建

突兀根从底层向上的回搭搭建二叉树

3.1设计过掉不符情况(在最底层时)

  • if(array == null) return, 没有元素不用排,下面是有元素
  • if(strat == end) return,只有一个元素不用排,下面是多个元素
  • if(strat > end) return,排不了不要排的,之后下面是符合正常情况的多个元素 

3.2查验能实现基础结果(在最底层往上点时)

当突兀根来到倒数第二层,当共有两个元素下突兀根去作为在上层的会去操作实现上层与下两层结果的表示连接时,左边、右边都是有序的结果,要实现它这层的有序结果要突兀根去操作实现为它的值比左边的都大、比右边的都小,操作具体实现为与1节点的值进行交换完成突兀根的实现操作,实现了突兀根所在的上层结果与下层左右两断开结果的连接表示,说明突兀根的实现操作在底层确实是能完成基础排序的


3.3跳转结果继续往上回搭


4.实质

用二叉树递归实现排序实质上还是确定元素大小排在的数组位置递归完一个个来排的

它排的位置左边都比它小、右边都比它大,它排的位置就是它在数组中排的大小位置同时也确定着其它元素的相对大小排位位置,所以最后一层元素不去找基准排位置也是相对已确定下来的不用去排,所以if(start == end)return的


二、快速排序的基准排序

待排序元素将其所在的待排序区域调整划分成以它为基准值左边都比它小、右边都比它大的两部分,并将它基准值放入两部分的中间就完成了此元素的排序

1.双路双向交换铺(Hoare法

1.1原理

要去排的元素基准值在待排序区域里面任意取好后,在待排序区域左右两端往内相遇铺路右端往内铺遇小不符等停左端往内铺遇大换过去交换直至路头遇相等,此时路头位置即基准元素大小排在的位置,最后将基准元素交换过去就完成了此元素的排序


1.2实现

private static int partition(int[] array, int left, int right) {int i = left;int j = right;int pivot = array[left];while (i < j) {while (i < j && array[j] >= pivot) {j--;}while (i < j && array[i] <= pivot) {i++;}swap(array, i, j);}swap(array, i, left);return i;}
1.2.1>=

遇到与基准值相等大小的元素时直接作为可行的路过掉的因为与基准值相等大小的元素到最后排序在此作为基准元素左右两边都是可以的,所以此时排放在基准的左右两路最后成两部分都是可以的


1.2.2先右再左

基准为路的相遇点,要设置在属于左路因为最后基准交换放到相遇点,基准值放到相遇点进去排序,相遇点的值会交换放到第一个位置即基准值的左边需要是左路的部分,所以每轮的铺路都是先进行右路的铺完到左边停再进行左路的铺


2.双路双向覆盖铺(挖坑法

2.1原理

要去排的元素基准值在待排序区域内任意取好并挖成坑从左右端先左或右都行往同向内互相埋坑时又挖坑地推坑推坑时始终是一端路停在坑位等着另一端路往内铺路挖到坑填上,所以左右路两端相遇时一定遇在坑位,此位置就是基准元素大小排序的位置排好


2.2实现

private static int partition(int[] array, int left, int right) {int i = left;int j = right;int pivot = array[left];while (i < j) {while (i < j && array[j] >= pivot) {j--;}array[i] = array[j];while (i < j && array[i] <= pivot) {i++;}array[j] = array[i];}array[i] = pivot;return i;}

3.双路单向交换铺(前后指针法

3.1原理

要去排序的基准元素在待排序区间任意选好后,定义prev与cur两前后指针,在排序区间的一端开始同向往另一端通过前后交换动态维护prev及之前的区间为小路cur及到prev之前的区间为大路,这样当cur遍历完排序区间时,数组就被分好了小路与大路两部分,再将基准元素交换放到prev指针位置处,一个基准元素就在待排序区间排好了


3.2实现

private static int partition(int[] array, int left, int right) {int prev = left ;int cur = left+1;while (cur <= right) {if(array[cur] < array[left] && array[++prev] != array[cur]) {swap(array,cur,prev);}cur++;}swap(array,prev,left);return prev;}

三、快速排序的复杂度

基准排序的特点

  • 元素的直接位置排好也排好着其它元素的间接位置排好减少着其它元素剩下的需要排的量
  • 每一个节点的出现,就是其完成它所在待排区域的基准排位标志 

1.时间复杂度

递归的调用语句算的是调用里面执行的内容(调用本身不算),每次调用里面的常量次数执行语句不算(因为乘常量常量可忽略的),只算里面的找调基准排的非常量级的时间复杂度,算时间复杂度时就一层层地算每层里面所有递归调用的时间和


1.1完全顺序逆序

1.1.1结构影响

当元素完全顺序或完全逆序排时,其呈现的二叉树结构为单分支的二叉树

  • 一层层下来每层里面只划分出了一个的递归调用它这样排能间接排出不用去排的元素只有一个(即只有一个叶子节点的元素)
1.1.2时间

最开始第一层时间是n-1,再下层一个元素已经排好了时间是n-2,到最后一层时最后一个元素被间接排好递归调用函数里面是直接return的,所以一共有n层,n-1层要去算时间,从上往下每层的时间从n-1减到1的等差数列和,最后大O算成的时间复杂度为O(n^2)实际上的时间会比n^2少


1.2完全二叉树序

1.2.1结构影响

当数组呈完全二叉树排列时:

  • 每个节点排时都有间接最大地去排着其它元素的位置,一层层下来在每层里剩下区域会越来越多地被划分着去排的,在一层中将会去完成更多的在区间中的排序,到最后一层能间接排出不用去排的元素会有很多
  • 一个区间里,元素去基准排划分的次数固定是元素个数少1的划分成更多的区间里去排,排序本身就会减这么区间多个的次数完成
1.2.2时间

因为每一层往下已排好的元素越来越多,每一层中所有基准区间总的去排的次数会越来越少,到最后一层里会有许多通过间接排就排好的元素不需要去排的,但大O算时的最后结果是偏大地算为每层所有找基准排的时间为固定的n,然后树的高度为log(n),时间复杂度为O(n*log(n))实际上的时间会比它少很多(根节点高度视为0的)


2.空间复杂度

因为递归调用的栈空间是动态复用的,所以空间复杂度为递归树的最大高度下算每层开辟的空间,因为这里每层递归函数里面开辟的空间是常量级,所以大O算排序递归的空间复杂度就为递归调用栈的深度即二叉树的高度

  • 当数组完全顺序或逆序时,二叉树的高度为n-1,空间复杂度为O(n)
  • 当数组呈完全二叉树排列时,二叉树的高度为log(n),空间复杂度为O(log(n))

3.优化

二叉树每层分支得越多装得越满

  • 每个元素节点都会去间接排其它元素的两部分位置、更多的在区间的排序减的次数会更多、以层单位去算时间的层的量会更少、从上往下已排出剩下的待排序元素会越来越少很多、最后通过间接排出位置不用去排的元素就会更多,时间复杂度会更低
  • 二叉树的高度更小下,空间复杂度也会更低

3.1三数取中

在每个待排序区间虽然是可以任意取元素作基准,但我们尽量取大小排在中间的元素使生成的树分支更多树更矮时间复杂度与空间复杂度都更低,我们采用三数取中法,即得到待排序区间后,在区间的首中尾的三个数比较下拿更小值更有可能得使得取的基准值大小更偏中一点


3.2插入排序

3.2.1栈溢出原因

当二叉树经上层已排好序节点能确定往下再分更多的更小的待排序区间去排序时,在二叉树下几层会分出很多的待排序子区间去排序,除了最底层的不需要去排序,其它在上层的每个区间的一次排序函数里都会执行到再调用下层的两个递归,在此时由于待排序子区间被分的特别多,会连续调用特别多的函数,一时间开辟特别多的函数栈帧,很有可能会造成栈溢出


3.2.2利与弊

因此在最后几层的许多待排序子区间去排序时,我们可以直接在倒数的上几层中就开始截断不再往下通过分更多的子区间去基准排序了直接在这一层将待排序区域用插入排序直接排好,因为经过上层的有很多元素已经排好了位置,剩下的待排序元素也是间接地比较有序的,用插入排序也可以高效地完成,就不用去开辟下层大量聚集的函数栈帧避免了栈溢出,降低了开辟空间的成本

但是由于快速排序原本最后一层的元素通过上层元素的排好序全部可以间接地不用去排直接排好的改成了插入排序后时间复杂度可能会比原来的纯快速排序更高了

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

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

相关文章

SoapUI 4.6.4(32位)下载安装教程 - 兼容老旧Windows系统

SoapUI 4.6.4&#xff08;32位版&#xff09; 是个老版本的测试工具&#xff0c;专门给 32位 Windows 电脑 用的。现在最新版都是 64 位的了&#xff0c;但如果你还在用老系统&#xff0c;可能还得找这个旧版。 SoapUI 4.6.4工具下载:https://pan.quark.cn/s/c07381db8102 这…

【AI量化第24篇】KhQuant 策略框架深度解析:让策略开发回归本质——基于miniQMT的量化交易回测系统开发实记

我是Mr.看海&#xff0c;我在尝试用信号处理的知识积累和思考方式做量化交易&#xff0c;应用深度学习和AI实现股票自动交易&#xff0c;目的是实现财务自由~ 目前我正在开发基于miniQMT的量化交易系统——看海量化交易系统。 本篇要讲到量化的核心了——策略。说白了每个投资者…

Java面试黄金宝典48

1. C++ 的拷贝构造函数,深拷贝和浅拷贝 定义 拷贝构造函数:在 C++ 里,拷贝构造函数属于特殊的构造函数,其功能是使用一个已存在的对象来初始化一个新对象。当对象以值传递的方式作为参数传给函数、函数返回对象、用一个对象初始化另一个对象时,拷贝构造函数会被调用。浅拷…

OpenCV学习之获取图像所有点的坐标位置(二)

1.功能介绍 (1)使用openCV解析了.jpeg、.jpg、.png格式的图像文件,输出了图像的宽、高、通道数; (2)创建txt格式文件,保存图像中各像素点的rgba值。 2.环境介绍 操作系统:window10 开发语言:visual studio 2015 c++ 3.功能实现过程 3.1环境设置 (1)打开Vs2015…

B2B2C多用户商城平台 的两种创新玩法

以前随便搞个淘宝京东那样的商城就能躺着赚钱的日子早过去了&#xff01;现在市面上各种电商玩法花样百出&#xff1a;小红书那种刷着刷着就下单的"种草"电商&#xff0c;拼多多那种"帮我砍一刀"的社交电商&#xff0c;还有抖音快手那种看着视频突然就想买…

【Bluedroid】A2DP Sink播放流程源码分析(二)

接上一篇继续分析&#xff1a;【Bluedroid】A2DP Sink播放流程源码分析(一)_安卓a2dp sink播放流程-CSDN博客 AVDTP接收端&#xff08;Sink&#xff09;流事件处理 bta_av_sink_data_cback 是 Bluedroid 中 A2DP Sink 角色的 AVDTP 数据回调函数&#xff0c;负责处理接收端的…

抗量子算法验证工具

抗量子算法计算工具 抗量子算法验证工具ML-KEMML-DSASLH-DSA 抗量子算法验证工具 2024年末&#xff0c;美国NIST陆续公布了FIPS-203、FIPS-204、FIPS-205算法标准文档&#xff0c;抽空学习了一下&#xff0c;做了个算法计算工具。 ML-KEM ML-DSA SLH-DSA 需要的朋友可留言交流…

2025年PMP考试有哪些变化?难点在哪里?

PMP&#xff08;项目管理专业人士资格认证&#xff09;考试因其广泛的行业认可度和实用性&#xff0c;成为许多专业人士提升职业竞争力的重要选择。然而&#xff0c;对于初次接触PMP考试的考生来说&#xff0c;其广度与深度的平衡、理论与实践的结合&#xff0c;以及跨文化思维…

Docker学习笔记-docker安装、删除

一、在centOS 7中docker的默认安装目录 # Docker 主配置文件目录 ls /etc/docker# Docker 数据目录&#xff08;镜像、容器、卷等&#xff09; ls /var/lib/docker# Docker 可执行文件路径 which docker # 输出类似 /usr/bin/docker 二、docker文件目录说明 目录/文件用途/…

MATLAB求和∑怎么用?

MATLAB求和∑怎么用&#xff1f; 一&#xff1a;题目&#xff1a;求下列方程的和 二、代码如下 1.syms函数 &#xff08;方法一) 代码如下&#xff08;示例&#xff09;&#xff1a; 1. syms x 2. symsum((x.^22*x).^3,1,100) 3. 2.直接用循环 (方法二) 代码如下&am…

每日算法-链表(2.两数相加、24.两两交换链表中的节点、143.重排链表)

一.两数相加 1.1题目描述 1.2题解思路 定义两个指针l1,l2依次遍历两个链表&#xff0c;用变量add存储l1加l2的值&#xff0c;将add的个位数取出来充当新节点的值&#xff0c;然后将add的个位数删去&#xff0c;即add /10&#xff0c;循环此操作。 重点分析&#xff1a; 1.跟…

Flutter学习 滚动组件(1):ListView基本使用

目录 一、ListView构造方法1.1 常规方法1.2 ListView.builder1.3 ListView.separated 二、自定义ListView样式和布局&#xff1a;三、ListView性能优化&#xff1a;总结&#xff1a; 一、ListView构造方法 主要以下几种方法&#xff1a; 常规方法&#xff0c;直接使用默认的构…

ESLint常见错误

1、Strings must use singlequote —— 字符串必须使用单引号 2、Extra semicolon semi——额外的分号&#xff1a;一行语句结尾不能添加分号 3、Unexpected trailing comma —— 行尾多了一个逗号 4、Newline required at end of file but not found ——文件结尾必须要新加…

Windows进行磁盘分区/扩容

Windows进行磁盘分区/扩容 导航 文章目录 Windows进行磁盘分区/扩容导航分区教程压缩卷教程 用Windows自带的磁盘管理进行分区/扩容&#xff0c;但有个东西需要说明下是&#xff1a; 物理特性限制 磁盘分区的物理特性决定了扩容操作的方向。在磁盘上&#xff0c;数据是线性存储…

获取类路径

分析 String pathThread.currentThread().getContextClassLoader().getResource("log").getPath(); 这行代码用于获取类路径(classpath)下名为"log"的资源的文件系统路径&#xff0c;我来详细解析它的执行过程和潜在问题&#xff1a; 1. 代码分解解析 j…

安装fvm可以让电脑同时管理多个版本的flutter、flutter常用命令、vscode连接模拟器

打开 PowerShellfvm安装 dart pub global activate fvm安装完成后&#xff0c;如果显示FVM无法识别&#xff0c;那么需要去添加环境变量path添加这个&#xff1a;C:\Users\Administrator\AppData\Local\Pub\Cache\bin 常用命令 fvm releases 查看用户可以装的flutter版本fvm l…

Kaggle-Disaster Tweets-(二分类+NLP+模型融合)

Disaster Tweets 题意&#xff1a; 就是给出一个dataframe包含text这一列代表着文本&#xff0c;文本会有一些词&#xff0c;问对于每条记录中的text是真关于灾难的还是假关于灾难的。 比如我们说今天作业真多&#xff0c;这真是一场灾难。实际上这个灾难只是我们调侃而言的。…

Flutter 2025 Roadmap

2025 这个路线图是有抱负的。它主要代表了我们这些在谷歌工作的人收集的内容。到目前为止&#xff0c;非Google贡献者的数量超过了谷歌雇佣的贡献者&#xff0c;所以这并不是一个详尽的列表&#xff0c;列出了我们希望今年Flutter能够出现的所有令人兴奋的新事物&#xff01;在…

如何通过API接口获取淘宝商品价格?实操讲解

要通过API接口获取淘宝商品价格&#xff0c;需使用淘宝开放平台&#xff08;Taobao Open Platform, TOP&#xff09;提供的商品详情API&#xff08;如taobao.item.get或taobao.item_get&#xff09;。以下是完整的实操步骤&#xff1a; 一、前期准备 注册淘宝开放平台账号 访问…

按键精灵安卓/ios脚本辅助工具开发教程:如何把界面配置保存到服务器

在使用按键精灵工具辅助的时候&#xff0c;多配置的情况下&#xff0c;如果保存现有的配置&#xff0c;并且读取&#xff0c;尤其是游戏中多种任务并行情况下&#xff0c;更是需要界面进行保存&#xff0c;简单分享来自紫猫插件的配置保存服务器写法。 界面例子&#xff1a; …