排序算法--快速排序

前提:

         快速排序(Quicksort)是对冒泡排序的一种改进。

        快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

hoare版本的快速排序算法分析与实现 : 

         hoare大佬的算法思想算是一道硬菜,容易咯牙那种,不如说快速排序所有版本都很有东西。

那么hoare大佬的算法思想是这样的:

有图我就喜欢上:

hoare版本的动图:

我们定义的一个基准位key;然后定义两个变量Left和Right,让Right从右向左找比a[key]小的数,让Left从左向右找比a[key]大的数。找到后让Left和Right交换,不断重复上述操作,直到right和left相遇,这时交换a[Left]和a[key](或者a[Right]和a[key]交换也行,毕竟Left和Right处在同一位置);让key的下标更新,这轮操作过后key的左边都比key小,key的右边都比key大。

 动图有点快,来个详细步骤:

右边先走没找到小,继续走;左边再走,没找到大,继续走;

右边再走,找到小,停住等待交换;

右边已经找到小,左边再走,找到大;二者可以交换;

交换

右边继续走,找到小,停住;

右边已经找到小,左边走,找到大;二者可以交换;

交换

右边再走,找到小,停住;左边走,与R相遇;a[L]和a[key]交换

交换

更新key的位置,本轮操作完成;

 上代码:

我们定义了变量left和right控制遍历;定义变量keyi=begin,确定基准位(基准位有很多选择,一般为了简便选择起始位置)。

然后我们循环遍历序列,让右边先走,没遇到比基准位小的就继续向左走,找到了就停住;左边一样,没找到大继续走,找到就停住;

左右都停住后,就交换。然后继续循环,直到左右相遇,这时外循环结束,交换基准位和left,更新key的位置;

   这里需要注意的是,right如果一开始就一直没有找到比a[key]小的数,一直找万一越过了left(这时是a[0])怎么办?这不妥妥的越界?因此我们应该如上图给循环添加限制条件(left<right)防止越界。left也是相同的处理。

上述代码完成后,做到了这个效果:即key的左边都比key小,右边都比key大。

如上图这样,key的左右其实并不有序。我们要做的是快速排序啊?即使是冒泡、直接插入排序排好都是完全有序的,快排难道这么拉吗?

      在前提中我们提到了, 快速排序是Hoare于1962年提出的,其基本思想为:任取待排序元素序列中 的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右 子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。所以,实际上快速排序是一种二叉树结构的交换排序方法。而二叉树的一大重点就是递归

 所以要做到完全排序我们应该:

完美的递归思想是不是?

完全排序就结束了,我们试着调试一下:

运行了,有问题。

问题就出在递归上,递归到最后只有一个元素或没有元素(见上面简易递归图),数组发生了越界,所以我们需要特殊处理:

当begin>=end时,说明只有一个元素或为空,这时说明序列有序,直接返回,不要再继续。

这样基本的hoare版本的排序就结束了。

 hoare版本的快速排序的小优化:

1、三数取中: 

三数取中是一种对快速排序的小优化,目的就是为了使基准数更加的小,提高后面的递归的效率;

话不多说,上代码:

 

  三数取中其实挺好理解的,就是取begin和end的中间值,比较三个数,哪个最小让其成为基准值。

2、小区间优化--直接插入排序优化:

    我们学习二叉树时,都知道递归的最后一层占据整个递归的50%左右,倒数第二层25%左右,第三层12.5%左右。因此,如果我们能对最后递归次数最多的几层进行优化,效率会有一定的提升。

  这就是快速排序的小区间优化的一种:直接插入排序优化:有不了解直接插入排序的可以看我的博客:排序算法——直接插入排序-CSDN博客

新增的这个判断就是当程序递归到此次,发现要排序的数目<=10,就不要再排序了,直接上直接插入排序(我们知道,直接插入排序对基本有序的序列排序效率是很高的)。

当然,这两种方法都是对直接插入排序的小的优化,甚至可能产生反效果。

直接插入排序的其他思想--挖坑法:

     不得不感慨,这个世界总是有大佬不断推动世界推陈出新,挖坑法就是一种针对hoare版本难理解研究出的另一种版本。

     挖坑法,顾名思义“挖坑”,它的骚操作是这样的:

     1、我们将第一个元素仍设置为基准位,将其中的值保存起来,将第一个位置作为坑位。

     2、我们依旧设置left和right,让right从右向左走,如果找到比基准位小的数,就将其存到坑位处,那么原right处就形成了新的坑位。然后left向右走找大,找到大就将其放到坑位处,这就又形成新的坑位。不断重复该操作,直到left和right相遇。

   3、这时我们保存的原基准位就发挥了作用,将其放到最后的坑位处,仍然达到了基准值左边都比他小,右边都比他大 的效果。

话有点多了,放图:

挖坑法比hoare版本的好理解一点,那么上代码:

这里我们定义Key保存我们选定的初始坑位的值。然后定义变量hole来代表坑的位置。

下面的代码与hoare版本大同小异。当循环结束后,即begin和end相遇,这时坑位就是最后基准值的最终位置。

因为这里我们是封装了这样一个函数来实现挖坑法的步骤,所以要传坑位参数给QuickSort函数来进行递归排序。

 直接插入排序的其他思想--前后指针法:

         这个世界大佬那么多,好的想法自然不会只有一个,前后指针法,就是另一个快速排序的算法思想。

        前后指针法,即使用一前一后两个指针,前指针寻找比基准值小的数,如果找到,后指针先后移一位,再与前指针所指的值做交换,前指针再++;如果遇到比基准值大的数,前指针继续++,后指针不移动。当前指针遍历完成整个序列时,将基准值与后指针指向的数交换。达到左边比基准值小,右边比基准值大的效果。

代码实现:

写个函数封装的一大好处就是可以再利用,哈哈~~

前后指针法,一大重点就是指针一前一后,前指针负责遍历,所以循环的继续条件就是要前指针不越界。然后,交换条件的判断也是一大毒点,要确保前指针指向的值小于基准值的同时,前后指针不能走到一起。这是为了确保我们不会将元素与其自身交换(这没有意义)。

 快速排序的时间复杂度:

           快速排序的时间复杂度是O(n^logn);

        

        

      

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

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

相关文章

【Leetcode每日一题】 综合练习 - 全排列 II(难度⭐⭐)(71)

1. 题目解析 题目链接&#xff1a;47. 全排列 II 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 算法思路梳理 为了生成给定数组nums的全排列&#xff0c;同时避免由于重复元素导致的重复排列&#xff0c;我们可以遵…

快速上手RabbitMQ

安装RabbitMQ 首先将镜像包上传到虚拟机&#xff0c;使用命令加载镜像 docker load -i mq.tar 运行MQ容器 docker run \-e RABBITMQ_DEFAULT_USERitcast \-e RABBITMQ_DEFAULT_PASS123321 \-v mq-plugins:/plugins \--name mq \--hostname mq \-p 15672:15672 \-p 5672:5672 …

如何使用 GPT API 从 PDF 出版物导出研究图表?

原文地址&#xff1a;how-to-use-gpt-api-to-export-a-research-graph-from-pdf-publications 揭示内部结构——提取研究实体和关系 2024 年 2 月 6 日 介绍 研究图是研究对象的结构化表示&#xff0c;它捕获有关实体的信息以及研究人员、组织、出版物、资助和研究数据之间的关…

brpc profiler

cpu profiler cpu profiler | bRPC MacOS的额外配置 在MacOS下&#xff0c;gperftools中的perl pprof脚本无法将函数地址转变成函数名&#xff0c;解决办法是&#xff1a; 安装standalone pprof&#xff0c;并把下载的pprof二进制文件路径写入环境变量GOOGLE_PPROF_BINARY_PA…

Microsoft 365 for Mac(Office 365)v16.84正式激活版

office 365 for mac包括Word、Excel、PowerPoint、Outlook、OneNote、OneDrive和Teams的更新。Office提供了跨应用程序的功能&#xff0c;帮助用户在更短的时间内创建令人惊叹的内容&#xff0c;您可以在这里创作、沟通、协作并完成重要工作。 Microsoft 365 for Mac(Office 36…

1. 深度学习笔记--神经网络中常见的激活函数

1. 介绍 每个激活函数的输入都是一个数字&#xff0c;然后对其进行某种固定的数学操作。激活函数给神经元引入了非线性因素&#xff0c;如果不用激活函数的话&#xff0c;无论神经网络有多少层&#xff0c;输出都是输入的线性组合。激活函数的意义在于它能够引入非线性特性&am…

【webrtc】MessageHandler 7: 基于线程的消息处理:切换main线程向observer发出通知

以当前线程作为main线程 RemoteAudioSource 作为一个handler 仅实现一个退出清理的功能 首先on message的处理会切换到main 线程 :main_thread_其次,这里在main 线程对sink_ 做清理再次,在main 线程做出状态改变,并能通知给所有的observer 做出on changed 行为。对接mediac…

clang:在 Win10 上编译 MIDI 音乐程序(二)

先从 Microsoft C Build Tools - Visual Studio 下载 1.73GB 安装 "Microsoft C Build Tools“ 访问 Swift.org - Download Swift 找到 Windows 10&#xff1a;x86_64 下载 swift-5.10-RELEASE-windows10.exe 大约490MB 建议安装在 D:\Swift\ &#xff0c;安装后大约占…

《金融研究》:普惠金融改革试验区DID工具变量数据(2012-2023年)

数据简介&#xff1a;本数据集包括普惠金融改革试验区和普惠金融服务乡村振兴改革试验区两类。 其中&#xff0c;河南兰考、浙江宁波、福建龙岩和宁德、江西赣州和吉安、陕西铜川五省七地为普惠金融改革试验区。山东临沂、浙江丽水、四川成都三地设立的是普惠金融服务乡村振兴…

手撸Mybatis(二)—— 配置项的获取

本专栏的源码&#xff1a;https://gitee.com/dhi-chen-xiaoyang/yang-mybatis。 配置项解析 在mybatis中&#xff0c;一般我们会定义一个mapper-config.xml文件&#xff0c;来配置数据库连接的相关信息&#xff0c;以及我们的mapperxml文件存放目录。在本章&#xff0c;我们会…

docker-compose启动mysql5.7报错

描述一下问题经过&#xff1a; 使用docker compose 部署mysql5.7 文件如下: 使用命名卷的情况下&#xff0c;匿名卷不存在该问题 services:mysql:restart: alwaysimage: mysql:5.7container_name: mysql-devports:- 3306:3306environment:- MYSQL_DATABASEdev- MYSQL_ROOT_PAS…

团队经理口才训练教案(3篇)

团队经理口才训练教案&#xff08;3篇&#xff09; **篇&#xff1a;基础口才训练 一、教学目标 让团队经理了解口才在团队管理中的重要性。 教授基础口才技巧&#xff0c;如发音、语速、语调等。 二、教学内容 口才的重要性 强调团队经理的口才能力对团队凝聚力、沟通…

详细介绍ARM-ORACLE Database 19c数据库下载

目录 1. 前言 2. 获取方式 2.1 ORACLE专栏 2.2 ORACLE下载站点 1. 前言 现有网络上已有非常多关于ORACLE数据库机下载的介绍&#xff0c;但对于ARM平台的介绍不多&#xff0c;借此机会我将该版的下载步骤做如下说明&#xff0c;希望能够一些不明之人提供帮助和参考 2. 获…

分享一篇关于AGI的短文:苦涩的教训

学习强化学习之父、加拿大计算机科学家理查德萨顿&#xff08; Richard S. Sutton &#xff09;2019年的经典文章《The Bitter Lesson&#xff08;苦涩的教训&#xff09;》。 文章指出&#xff0c;过去70年来AI研究走过的最大弯路&#xff0c;就是过于重视人类既有经验和知识&…

Flutter笔记:美工设计.导出视频到RIVE

Flutter笔记 美工设计.导出视频到RIVE - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28…

目标跟踪—卡尔曼滤波

目标跟踪—卡尔曼滤波 卡尔曼滤波引入 滤波是将信号中特定波段频率滤除的操作&#xff0c;是抑制和防止干扰的一项重要措施。是根据观察某一随机过程的结果&#xff0c;对另一与之有关的随机过程进行估计的概率理论与方法。 历史上最早考虑的是维纳滤波&#xff0c;后来R.E.卡…

原生IP和住宅IP有什么区别?

原生IP和住宅IP在多个方面存在显著的区别。 从定义和来源来看&#xff0c;原生IP是指未经NAT&#xff08;网络地址转换&#xff09;处理的真实、公网可路由的IP地址&#xff0c;它直接从互联网服务提供商&#xff08;ISP&#xff09;获得&#xff0c;而不是通过代理服务器或VP…

【MATLAB】解决不同版本MATLAB出现中文乱码的问题

解决不同版本MATLAB出现中文乱码的问题 方法1&#xff1a;更改保存类型为GBK方法2&#xff1a;记事本打开方法3&#xff1a;Notepad参考 低版本matlab打开高版本Matlab的.m文件时&#xff0c;出现中文乱码问题。比如下图&#xff1a; 出现原因为&#xff1a; 编码格式不统一问…

批量抓取某电影网站的下载链接

思路&#xff1a; 进入电影天堂首页&#xff0c;提取到主页面中的每一个电影的背后的那个urL地址 a. 拿到“2024必看热片”那一块的HTML代码 b. 从刚才拿到的HTML代码中提取到href的值访问子页面&#xff0c;提取到电影的名称以及下载地址 a. 拿到子页面的页面源代码 b. 数据提…

Ansys Speos|进行智能手机镜头杂散光分析

本例的目的是研究智能手机Camera系统的杂散光。杂散光是指光向相机传感器不需要的散光光或镜面光&#xff0c;是在光学设计中无意产生的&#xff0c;会降低相机系统的光学性能。 在本例中&#xff0c;光学透镜系统使用Ansys Zemax OpticStudio (ZOS)进行设计&#xff0c;并使用…