排序进阶----快速排序

        当我们写了插入和希尔排序后,我们就应该搞更难的了吧。大家看名字就知道我们这篇博客的内容了吧。而且从名字上来看。快速排序就很快吧。那么为什么这个排序怎么能叫快速排序啊。我们希尔排序不是很快嘛。那么我们的快速排序肯定是有特殊之处嘞。不然这就太自负了。而且对于快速排序是用上了我们以前学的知识,二叉树。那我们为什么这么说嘞。我们下面就来讲讲嘛。

快速排序的思路

       其实对于看快速排序来说,我们理解的话还算是比较简单的。为什么这么说了,因为大家都已经大概了解了二叉数的用法了吧。我们这个快速排序设置一个值,但是这个值就是数组里面的,然后以他为主来左右行走。就是数组的头和尾,然后向中间寻找遇见比他大或者比他小的数,然后就进行交换,直到他们相遇。他们如果相遇了,那么可以表明的一件事就是他们相遇的地点一定会比我们设定的值大或者小。那么之所以会这样子呢,我们后面在实现的时候再谈论。所以总之上面我们说的就是把这个数组从左右两边开始移动后边的如果比我们设定值小,就先暂时停留,然后左边向中间移动,如果遇见比我们设定的值大的话就暂时停留,然后他们两个交换。接着继续往前走,如果他们两个相遇了的话,我们也能确定他们相遇的值是否比设定的值大或者小。后当他们相遇了之后,这就能用上我们二叉树的内容了。然后我们分左边和右边递归来实现这个。

快速排序的实现 

       当然实现快速排序的话,我们也还是像以前一样。先来写一个单趟。然后再实现整整体的过程。那么我们上面也说过了,需要先设定一个基准值。那我就先普遍设为头节点。当我们设置头节点后,我们还要向左右移动。那么我们这个还要再设置两个。那我当我们设置完这些之后,我们就可以开始向中间移动了。但是移动我们也有一个先后吧,到底是左先动还是右先动?如果我们以右先动的话,那么就是先找比我们设定值小的值就停下来然后就是左边移动。那么就会遇见比设定值小的值停下来。当达到这个目标之后我们就进行交换。知道他们两个相遇之后就结束。然后与这个值与我们的设定值进行交换。大家可能会想你怎么知道他们相遇的值会我设定的值小?这个大家需要先想一下。我们是让右边先走的。如果他们相遇,那肯定是右边走到了比他小的子才会停下来。然后左边才走。那么这是不是就确定了他们相遇的值比设定的值小。那么我们已经退出循环了,所以我们需要在手动的调整一下。这样,我们这单趟就结束了。

void xixi(int* a, int zuo, int you)
{//key确定基准值int key = zuo;int left = zuo;int right = you;while (left < right){//right先行动,找到比key小的值while (left < right && a[right] >= a[key]){right--;}//left行动,找到比key大的值while (left < right && a[left] <= a[key]){left++;}//到达指定位置,进行交换swap(&a[left], &a[right]);}//走完上面的步骤后,两个下标会相聚在一个位置//然后对这两个位置的值进行交换swap(&a[right], &a[key]);
}

        上面就是快速排序的单趟排序了,看起来是不是还是比较简单啊。就是比较确定下标然后交换数组的值。那么我们刚开始说过 快速排序是会用到二叉树的内容。我们既然单趟了那么下一趟怎么走呢?我不知道日常树就是递归值不一样而已。那么我们只需要将传进去的递归值改变从他们两个相遇的地方划分成为两部分,然后分为左部分和右部分。然后再分别理赔,周而复始,这样就排序好了。大家想想是不是这样的?所以在单趟排序的时候,我们还有一个事情需要处理一下,就是将key的值改变我们在最后的交换把key的改变写上,然后递归实现。

void QuickSort(int* a, int begin, int end)
{//结束条件if (begin >= end){return;}//一趟的实现int left = begin;int right = end;int keyi = left;while (left < right){//右边开始行动   一定要加上等于,因为快速排序找的是一定比它小的值while (left < right && a[keyi] <= a[right]){right--;}//左边开始行动while (left < right &&   a[left] <= a[keyi]){left++;}swap(&a[left], &a[right]);}swap(&(a[keyi]), &(a[right]));keyi = right;//[begin,keyi-1] keyi [keyi+1,end]QuickSort(a, begin, keyi - 1);//递归传递值QuickSort(a, keyi + 1, end);
}

         上面就是快速排序的基本方法了。当然都说只是基本方法了,那么他肯定还可以再进行优化。那他有哪些地方可以优化呢?我们接下来就来讲讲这些。

快速排序的优化 

1:      首先我们对于快速排序的优化就是我们最重要的key的值。我们快速排序,为什么key的值就始终是头节点了,我们不能换一个更加好一点儿的吗?所以我们的快速优化的第一个就是更改key的值。那么我们需要递归很多事,所以key的值需要更换很多次。那么我们就要写一个子函数来专门确定key的值。但是如何确定啊?这里就要用前辈的思想了。叫做三数取中。我们传递数组,和开头和结尾,然后我们计算开头和结尾中间的值比较,我们取中间的值,这样我们的快速排序就更加快速了。实现很简单:

//三数取中
int GetMid(int *a, int begin, int end)
{int mid = (begin + end) / 2;//平均的下标值if (a[begin] > a[end])//假设头大于尾的话{if (a[end] > a[mid])//尾大于平均那么尾就是中间的return end;else if (a[mid] > a[begin])//如过平均大于头的话头是中间值return begin;else//就只剩平均值了return mid;}else//(a[begin] < a[end])假设头大小于尾的话{if (a[end] < a[mid])//平均大于尾。则为是中间return end;else if (a[begin] < a[mid])//平均大于头的话,平均就是中间return mid;else//就只剩头了return begin;}
}

2:          另外一个优化方法就简单粗暴了许多了。因为我们都说快速排序嘛,要比我们前面学了几个排序都要好一些,而且我们也知道我们前面写的几个排序中插入排序对。小数组计算更快。我们就判断如果数组大于十的话,我们就快拍,如果小于十的话,我们就用插入排序。这就是大的用大的方法,小的用小的方法,这样我们是不是要方便许多? 但是我们要注意1.插入排序之后两个参数,一个是数据集合的起点地址,第二个是数据量。2.使用插入排序时,我们要传入待排序数据集合的其实地址,即a+begin,如果传入的是a,那排序的永远都是数组a的前n个区间。3.插入排序传入的是数据个数,所以我们要将end-begin加上1之后才传入。快速排序中end、begin都是闭区间(即数组下标)。如果大家对于插入排序还是不了解的话,可以看一下我上一篇博客。

void QuickSort_Pointer(int* a, int begin, int end)
{if (begin >= end){return;}//数据区间大与10,进行快速排序if (end - begin > 10){int prev = begin;int cur = begin + 1;int keyi = begin;//三数取中后对keyi位置的值进行交换int mid = GetMid(a, begin, end);swap(&a[mid], &a[keyi]);while (cur <= end){if (a[cur] < a[keyi] && ((++prev) != cur)){swap(&a[cur], &a[prev]);}cur++;}swap(&a[prev], &a[keyi]);keyi = prev;//开始进行递归QuickSort_Pointer(a, begin, keyi - 1);QuickSort_Pointer(a, keyi + 1, end);}else{//左闭右闭InsertSort(a, end - begin + 1);InsertSort(a + begin, end - begin + 1);}}
总结

      那么说明的就是我们快速拍摄的大概所有内容了。当然还有一种优化其实也是可以的,叫做挖坑法。这个如果大家感兴趣的话可以自己去了解一下。当然我的内容是不是很完全的。所以大家可以在评论区里面也说一下,自己感兴趣的话,我下一篇博客会补充的。

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

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

相关文章

autodl服务器中YOLOx训练自己数据集

目录 本篇文章主要讲解使用YOLOx训练自己数据集&#xff0c;其中包括数据集格式转换~ 目录 一、数据集处理二、环境配置三、配置文件修改四、开始训练五、开始验证 一、数据集处理 第一步&#xff1a;将yolo格式的数据集转换成VOC格式 转换脚本&#xff1a;txt_to_xml.py f…

Unity DOTS技术(二)ECS

文章目录 一.ECS简介二.基本操作实例三.实体查看组件四.位置实体修改五.旋转实体六.了解原有属性七.禁止自动创建八.动态实例化 一.ECS简介 ECS全称 (Entity Component System).即(E:实体 C:组件 S:系统). 实际上即是数据方法分离.数据放在组件里,具体实现放在系统里.组件挂载…

Debian系统磁盘挂载

服务器推荐&#xff1a;雨云 优惠码&#xff1a;zsj 用优惠码注册账户并绑定微信后可获取首月5折优惠券&#xff1b; 后续新购主机也可在积分商城中换取新购优惠券&#xff1b; 公测阶段的超大带宽服务器&#xff0c;由于是国内主机因此需要备案域名。 公测阶段价格尚未确定&am…

google的chromedriver最新版下载地址

Chrome for Testing availability (googlechromelabs.github.io) 复制对应的地址跳转进去即可下载&#xff0c;下载前先看下自己google浏览器版本&#xff0c;找到对应的版本号去下载&#xff0c;把解压缩的exe放到google浏览器目录下。

使用python统计word文档页数

使用python统计word文档页数 介绍效果代码 介绍 使用python统计word文档的页数 效果 代码 import os import comtypes.clientdef get_word_page_count(docx_path):try:# Initialize the COM objectword comtypes.client.CreateObject(Word.Application)word.Visible False…

Nature Communications|柔性自驱动仿生眼(离子凝胶/仿生眼/柔性电子)

2024年4月10日,黄维(Wei Huang)院士、南京工业大学刘举庆(Juqing Liu)教授和刘正东(Zhengdong Liu)副教授课题组,在《Nature Communications》上发布了一篇题为“A bionic self-driven retinomorphic eye with ionogel photosynaptic retina”的论文,罗旭(Xu Luo)、陈晨(…

ESP-01S 使用 arduino 烧录程序

一、设置 arduino 编辑器 1、文件-首选项-附加开发版管理网址中添加 http://arduino.esp8266.com/stable/package_esp8266com_index.json 2、工具-开发板管理 搜索 8266 并下载 ) 3、工具-开发板 在 8266 里面选择 Generic ESP8266 Module 4、工具-端口 记得选择对应的端口 …

【简单讲解下Fine-tuning BERT,什么是Fine-tuning BERT?】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

STM32作业实现(五)温湿度传感器dht11

目录 STM32作业设计 STM32作业实现(一)串口通信 STM32作业实现(二)串口控制led STM32作业实现(三)串口控制有源蜂鸣器 STM32作业实现(四)光敏传感器 STM32作业实现(五)温湿度传感器dht11 STM32作业实现(六)闪存保存数据 STM32作业实现(七)OLED显示数据 STM32作业实现(八)触摸按…

数据库(16)——DQL执行顺序

DQL的执行顺序 这是DQL的编写顺序。 而实际的执行顺序为

【LeetCode:575. 分糖果+ 哈希表】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

职场思考-在行业坚守中实现个人增值(13)

滚石不生苔&#xff0c;转行不聚财 在自己工作几年后&#xff0c;职业竞争力会由专业能力向行业经验进行转化 如果你不具备足够的行业积累&#xff0c;即使在某个专业上有足够的能力&#xff0c;你也难以得到待遇或职位的提升&#xff0c;陷入高不成低不就的局面 掌握完成岗位工…

记一次SpringCloud OpenFeign 服务调用传递 token @Async 上下文信息获取失败

一、场景 在异步方法中使用了feign调用&#xff0c;发现提示“您还未登录或登录已失效”。那原因很明了就是我的登录信息没办法传入到feign的调用方法里。 二、考虑的解决办法 1&#xff09;尝试一&#xff1a;ServletRequestAttributes attributes (ServletRequestAttrib…

【C语言进阶】文件操作:文件的打开与文件的读写以及文本文件和二进制文件

目录 1、为什么使用文件 2、什么是文件 2.1 程序文件 2.2 数据文件 2.3 文件名 3、文件的打开和关闭 3.1文件指针 3.2文件的打开与关闭 4、文件的顺序读写 4.1 几个函数的区别 5、文件随机读写 5.1 fseek 5.2 ftell 5.3 rewind 6、文本文件和二进制文件…

springboot+vue+mybatis超市管理-简单版+PPT+论文+讲解+售后

使用旧方法对超市信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在超市信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。 这次开发的小型超市管理系统有管理员&…

探索DIYGW可视化开发工具:提升UniApp项目效率与质量的新途径

一、引言 在快速迭代和不断创新的移动应用开发领域中&#xff0c;开发者们常常面临着一个共同的挑战&#xff1a;如何在保证开发质量的同时&#xff0c;缩短开发周期。近期&#xff0c;一款名为DIYGW的可视化开发工具进入了我们的视野&#xff0c;它以其独特的拖拽式开发方式和…

算法题-给定一个日期,输出星期几

目录 给定日期&#xff0c;输出对应是星期几 测试结果 如1900年 5月6日是星期三&#xff0c;计算给的日期是星期几 给定日期&#xff0c;输出对应是星期几 #include <stdio.h> #include <stdlib.h> #include <string.h>int main() {char input[100];int d…

如何被谷歌收录?

最简单的方法就是提交网站给谷歌&#xff0c;但这种方法可操作空间不大&#xff0c;一天一般也就只有十条左右的链接可以提交&#xff0c;对于一些大网站来说&#xff0c;这种方法显然不适用&#xff0c;这时候GPC爬虫池的好处就体现了&#xff0c;GPC爬虫池对希望提升Google搜…

Deepin Linux 深度 V23 beige 官方源及换镜像源方法。

Deepin Linux 深度 V23 英文版本号&#xff1a;beige 谁起的烂名字。。。。。。 1. 打开文件管理器&#xff0c;在apt文件夹点右键&#xff08;以管理员身份打开&#xff09;&#xff0c; 2. 输入你的登录密码&#xff0c;以便打开文件夹&#xff08;管理员权限&#xff09;。…

【MySQL数据库】索引与事务

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【MySQL】探秘&#xff1a;数据库世界的瑞士军刀 目录 &#x1f5f3;️一.索引 &#x1f4ee;1.工作原理 &#x1f4ec;2.类型 &#x1f4ed;3.作用 &#x1f4ea;4.优缺点 &#x1f4eb;5.使用…