排序之快速排序

快速排序之所以叫快速排序,肯定要配得上它的名字。我们就来看看它是如何这么快的。

快速排序的原理

快速排序是霍尔创建的,是通过以第一个或者最后一个数值作为比较值key,形成一个它的左边比它都小,右边比它都大的情况,然后把这个再成左右两个部分重复这个操作,一直细化。

霍尔版本

而霍尔的方法就是左右(l,r)两个指针向中间靠近,如果l遇到的值比key的值大就停住,r遇到比key小的值也停下,然后交换l,r的值,一直重复这个操作到两个指针相遇,将相遇的值与key交换就是最终要完成的情形

我们来分析一下这个过程

首先r先走找到5比6小,然后l走找到7

然后交换两者

继续这个操作,r先走,l后走找到4和9

然后交换

然后重复,r先走找到3,l后走与它相遇,相遇就停止

然后交换3和key

key就到了中间,形成我们需要到这个情况

接下来就是将这个操作分成左右两个,key左边重复操作,右边也是一样。那么这个操作会迭代出两个分支,然后一直二分下去,一直要l>=r的时候我们就停止。

我们很明显的发现可以用递归来完成这个操作。

提醒点

我一直在强调现r走再l走肯定有原因,主要是保证任何时候key和重合地方交换的时候,k都是比这个值大的。

那么我们就来证明一下:

循环结束的情况只有两种,一种是l撞到r,一种是r撞到l

第一种:因为是l撞到r,说明r已经走了,那么r停的地方一定是比key要大的,所以最后交点比

key大。

第二种:这种情况是出现在上一次,l和r交换后的,原先r的值交给了现在的l,那么现在的r重合于r就是之前r的值,之前r停止是比key大的,所以还是比key大。

综上任何情况都是比key大的。

如果我们反过来先让l走,那么不会出现上面的情况。

挖坑法

挖坑发就是先把key处的值取出来,然后就只有一个坑需要其他的值填,那么就让r向前走找到比key小的值放到坑出,那么现在r的地方又有一个坑,我们就要l向后走找比key大的值填坑。然后又是r,又是l...一直到两个相遇。最后一个坑就由key填下。

前后指针法

前后指针法相对有点抽象:

cur遇到比key小的就和++prev交换

上面是快排最基础的形式

还存在一定的缺陷,我们往下看

缺陷

上面三种都是有缺陷的

当排的是顺序数据的时候时间复杂度会坍缩成N²,并且会导致递归深度太深栈溢出。

霍尔和挖坑是差不多的,当r往前移动会在第一个相遇,然后分为左右,第二次递归的右边会在第二个下标相遇,然后第三个一直到末尾。就是N²。

前后指针法的cur会一直往后到循环结束,然后递归到下一次。也是n²的时间复杂度。

为了防着这种情况,有一个三数取中的算法让l,mid,r中第二大的数搞到最开始,这样可以尽可能的保证一趟排序完后key左右两边的长度大概相同。

然后我们将之前的三段代码写成单趟的:

那么可以变成这样写 

优化

我们看到递归是二分的,那么就像二叉树一样。那么最后一层递归量相当于前面的一半,而且最后一层也没有多大长度。我们就可以用其他的排序来解决:

防栈溢出

用递归还是有栈溢出的风险,所以我们安排非递归:

用栈也是可以的,模仿递归。

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

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

相关文章

redHat9 安装 iptables 过程记录

1. redHat9安装 iptables: 方法1:对于使用 yum 的旧版 Red Hat 9: yum install iptables-services 方法2:对于使用 dnf 的新版 Red Hat 9 或 CentOS: dnf install iptables ps: 可能会报错,诸如 connect f…

家用电器信息管理系统

摘 要 随着互联网的快速发展,传统家电行业受到冲击,逐渐向智能家居市场转型。因此,智能家居无疑是一个有着巨大市场需求和新兴发展空间的新兴产业,也是人们追求安全、便捷、舒适的生活方式的必然趋势。互联网推动了我国传统家居产…

从复用性角度阐述中台建设

目录 复用性中台定义深思中台建设产品线形态何时演变中台能力落地中台 业务中台架构总结 技术学习永不止步,最近也是看了很多关于架构设计相关的专栏,慢慢总结出来一部分知识,代入自己的思考与理解,以及结合并反思自己之前公司的架…

transformers Tokenizer

☆ 问题描述 Tokenizer的学习笔记(Tokenizer is all you need) Tokenizer用于数据预处理 - 分词 - 构建词典 - 数据转换 - 数据填充与截断 现在Tokenizer可以做到上面的所有事情。 ★ 解决方案 Tokenizer的基本使用 # 导入Tokenizer from transforme…

java经典面试题--进程和线程的关系/区别

进程和线程的定义以及作用 进程:进程是操作系统分配资源的基本单位,是程序的一次执行过程,它包括了程序执行的上下文环境,包括程序代码、数据、系统资源(内存、文件、设备等)以及执行状态等信息,其作用是提供一个独立的执行环境,…

【18.0】JavaScript---事件案例

【18.0】JavaScript—事件案例 【一】开关灯事件 【介绍】设置一个按钮,按下按钮触发事件,来回切换圆形图片的颜色 【分析】 图片设置:设置成圆形的图片背景颜色:设置红绿两个颜色,来回切换按钮设置:点击…

鸿蒙开发通信与连接:【@ohos.nfc.tag (标准NFC-Tag)】

标准NFC-Tag 本模块主要用于操作及管理NFC Tag。 说明: 本模块首批接口从API version 8开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 导入模块 import tag from ohos.nfc.tag;tag.getNfcATag getNfcATag(tagInfo: TagInfo): Nf…

Codeforces Global Round 26 E. Shuffle(树形dp)

题目 思路来源 乱搞ac 题解 注意到提出一个点之后, 后面第二次提出的点、第三次提出的点, 如果后续成为叶子,一定不相邻,所以等价于求原树的最大独立集 但是第一次提出的叶子可以和第二次提出的叶子相邻 这个看最后一个样例…

Java按照GBK拼音顺序对汉字排序

最近遇到一个需求,需要对一个列表数据的特定字段,比如姓名,初看应该不难,但是有什么比较快速便捷的方法,因为是Java的项目,所以想到比较火的工具框架Hutool,在Hutool官网 找到一个比较器类Pinyi…

python离线安装第三方库、及其依赖库(单个安装,非批量移植)

文章目录 1.外网下载第三方库、依赖库2.内网安装第三方库3.补充附录内网中离线安装python第三方库,这时候只能去外网手动下载第三方库,再传回内网进行安装。 问题是python第三方库往往有其前置依赖包,你很难清楚某个第三方库依赖的是哪些依赖包,更难受的是依赖包可能还有其…

CyclicBarrier改善CountDownLatch循环重入

CyclicBarrier 跟CountDOwnLatch非常类似,也是计时结束执行。 区别就是可以重用,也就是基数可以回到初始值。用完了不需要重新创建对象。 谁调用await就阻塞谁,这个能阻塞多个,countdownlatch只能阻塞一个。 变为0之后 再次调用…

如何集成 Spring Security 和 JWT,

关键问题: 如何集成 Spring Security 和 JWT,并实现用户认证和授权? SpringSecurity核心是一组过滤器链,JWT是生成token的机制 代码操作: 关于jwt: 1.yml配置中加入jwt配置信息 2.JWT token的JwtUtils.java--生成…

五十一、openlayers官网示例Layer Min/Max Resolution解析——设置图层最大分辨率,超过最大值换另一个图层显示

使用minResolution、maxResolution分辨率来设置图层显示最大分辨率。 <template><div class"box"><h1>Layer Min/Max Resolution</h1><div id"map" class"map"></div></div> </template><…

leetcode-13-[110]平衡二叉树[257]二叉树的所有路径[404]左叶子之和[222]完全二叉树的节点个数

一、[110]平衡二叉树 注意&#xff1a;注释的1、2两处得有返回值-1 class Solution {public boolean isBalanced(TreeNode root) {int result getHeight(root);return result ! (-1);}//高度public int getHeight(TreeNode node){if(nodenull){return 0;}int lh getHeight(…

Java 8 Stream API介绍

Java 8引入了Stream API&#xff0c;这是对集合框架的一种增强&#xff0c;它允许你以一种声明式的方式处理数据集合。Stream API的核心在于将数据的操作分为两个主要阶段&#xff1a;中间操作和终端操作。中间操作返回的是一个新的Stream&#xff0c;可以链式调用多个中间操作…

基于Windows API DialogBox的对话框

在C中&#xff0c;DialogBox函数是Windows API的一部分&#xff0c;它用于在Win32应用程序中创建并显示一个模态对话框。DialogBox函数是USER32.DLL中的一个导出函数&#xff0c;因此你需要在你的C Win32应用程序中链接到这个库。 #include "framework.h" #include …

网信办公布第六批深度合成服务算法备案清单,深兰科技大模型入选

6月12日&#xff0c;国家互联网信息办公室发布了第六批深度合成服务算法备案信息&#xff0c;深兰科技硅基知识智能对话多模态大模型算法通过相关审核&#xff0c;成功入选该批次《境内深度合成服务算法备案清单》。同时入选的还有腾讯混元大模型多模态算法、支付宝图像生成算法…

个人职业规划(含前端职业+技术线路)

1. 了解自己的兴趣与长处 喜欢擅长的事 职业方向 2. 设定长期目标&#xff08;5年&#xff09; 目标内容 建立自己的品牌建立自己的社交网络 适量参加社交活动&#xff0c;认识更多志同道合的小伙伴寻求导师指导 建立自己的作品集 注意事项 每年元旦进行审视和调整永葆积极…

【MySQL】(基础篇十五) —— 增删改数据

增删改数据 本文介绍如何利用SQL的INSERT语句将数据插入表中。以及如何利用UPDATE和DELETE语句进一步操纵表数据。 数据插入 INSERT是用来插入&#xff08;或添加&#xff09;行到数据库表的。插入可以用几种方式使用 插入完整的行&#xff1b;插入行的一部分&#xff1b;插…

jquery动态效果插件之ScrollMagic

ScrollMagic 是一个强大的 JavaScript 库,可以帮助开发者在页面滚动时触发各种动画效果。它支持复杂的滚动交互,非常适合制作富交互的网页。 这里他使用了ScrollMagic的几种滚动效果: 视差滚动效果:页面上的一些元素在滚动时会产生视差滚动效果,即元素以不同的速度移动,营造出…