【排序】快速排序实现
目录
一、快速排序是什么?
二、左右指针法
1.实现原理
2.代码如下:
三、挖坑法
1.实现原理
2.代码如下:
四、前后指针法
1.实现原理
2.代码如下:
五、三数取中
1.实现思想
2.代码如下:
3.使用方法
总结
前言
快排是公认的排序效率之王,加上三数取中与小区间优化更是无人能敌。
一、快速排序是什么?
快排分为三种实现方式:
①左右指针法
②挖坑法
③前后指针法
其中左右指针与挖坑法实现原理差不多一样:(只是挖坑法多创建一个临时变量存储坑中的数据)它们俩都是选大的的通过自己的方式放在后面,选出小的通过自己的方式放前面,通过递归就可将整个数组进行排序。
前后指针法同样是选大的放后面,选小的放前面,但是与上面两个不同的是它只从一头开始遍历。
二、左右指针法
1.实现原理
① 定义两个指针,一个从左边遍历,一个从右边遍历。
② 定义一个key值用来做比较的基准值。
③ 如果key是最左边的值,那么就让right先向左找小值,反之,就让left先找大值。
目的:在left与right相遇时,在与key值交换时能够交换大值(小值),否则会出现数据错误。
④ 假定key值定义为最左边的数字,
right向左走找比key值大的数据,找到后停下,
left向右走找比key值小的数据,找到后停下,
此时交换left与right对应的值,循环往复直至left与right相遇。
⑤ 相遇后,将相遇点与keyi对应的数据进行交换,此时数组将会达到key左边的数字都小于key,右边的数字都大于key,后续通过递归可实现整个数组的排序。
2.代码如下:
#include <stdio.h>void swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}
// 左右指针法
void QuickSort1(int* arr, int begin, int end)
{if (begin >= end){return;}int left = begin;int right = end;int keyi = left;while (left < right){// right向左找小while (left < right && arr[right] >= arr[keyi]){right--;}while (left < right && arr[left] <= arr[keyi]){left++;}// key的大值与小值进行换位swap(&arr[left], &arr[right]);}// 左右指针相遇,与key换位int meeti = left;swap(&arr[meeti], &arr[keyi]);QuickSort1(arr, begin, meeti - 1);QuickSort1(arr, meeti + 1, end);
}
int main()
{int arr[] = { 5,3,6,9,8,7,2,0,1,4 }; size_t len = sizeof(arr) / sizeof(arr[0]);QuickSort1(arr, 0, len - 1);return 0;
}
三、挖坑法
1.实现原理
挖坑法与左右指针法大致相同。
① 选出一个key值,并将其所在的位置定为坑(坑可被覆盖 -> 放数据,坑中的数据被保存在了key中)
② 定义两个指针,一个从左边遍历,一个从右边遍历。
③同左右指针法相同,
如果key是最左边的值,那么就让right先向左找小值,反之,就让left先找大值。
目的:在left与right相遇时,在与key值交换时能够交换大值(小值),否则会出现数据错误。
④ 假定key值定义为最左边的数字:
right找到比key值大的数据停下,将此数入坑,同时right所在的位置变为新坑;
left向右走找比key值小的数据,找到后停下,将此数入坑,同时left所在的位置变为新坑;
循环此过程直至两指针相遇。
⑤ 将key值入坑,此时数组将会达到key左边的数字都小于key,右边的数字都大于key,后续通过递归可实现整个数组的排序。
2.代码如下:
// 挖坑法
void QuickSort2(int* arr, int begin, int end)
{if (begin >= end){return;}int left = begin;int right = end;int key = arr[left];int pivot = left;while (left < right){// right向左找小while (left < right && arr[right] >= key){right--;}// 入坑,更新坑位arr[pivot] = arr[right];pivot = right;// left向右找大while (left < right && arr[left] <= key){left++;}arr[pivot] = arr[left];pivot = left;}// 相遇,key值入坑arr[pivot] = key;QuickSort2(arr, begin, pivot - 1);QuickSort2(arr, pivot + 1, end);
}// 挖坑法
void QuickSort2(int* arr, int begin, int end)
{if (begin >= end){return;}int left = begin;int right = end;int key = arr[left];int pivot = left;while (left < right){// right向左找小while (left < right && arr[right] >= key){right--;}// 入坑,更新坑位arr[pivot] = arr[right];pivot = right;// left向右找大while (left < right && arr[left] <= key){left++;}arr[pivot] = arr[left];pivot = left;}// 相遇,key值入坑arr[pivot] = key;QuickSort2(arr, begin, pivot - 1);QuickSort2(arr, pivot + 1, end);
}
int main()
{int arr[] = { 5,3,6,9,8,7,2,0,1,4 }; size_t len = sizeof(arr) / sizeof(arr[0]);QuickSort1(arr, 0, len - 1);return 0;
}
四、前后指针法
1.实现原理
① 定义两个指针,一前(cur)一后(prev)。
② 定义一个key值,用来作为单趟排序的基准值。
② 让前面的指针继续向前遍历,如果找到比key值小的,++prev后与其交换。
③ 重复②直至cur到达数组末尾,交换prev与keyi对应的数据。
④ 此时数组将会达到key左边的数字都小于key,右边的数字都大于key,后续通过递归可实现整个数组的排序。
2.代码如下:
// 前后指针法
void QuickSort3(int* arr, int begin, int end)
{if (begin >= end){return;}int left = begin;int right = end;int key = arr[left];int prev = left;int cur = prev + 1;while (cur <= end){if (arr[cur] < key && ++prev != cur)// 减少不必要的swap{swap(&arr[prev], &arr[cur]);}++cur;}swap(&arr[prev], &arr[begin]);QuickSort3(arr, begin, prev - 1);QuickSort3(arr, prev + 1, end);
}int main()
{int arr[] = { 5,3,6,9,8,7,2,0,1,4 }; size_t len = sizeof(arr) / sizeof(arr[0]);QuickSort3(arr, 0, len - 1);return 0;
}
五、三数取中
1.实现思想
当待排序数组本来是逆序时,快排效率将降到最低,为O(N2),每次都许哟啊对每个数进行交换位置2次,所以产生了三数去中的方法:
取得数组最开始、最末尾、最中间中的中间值来平衡key值。
2.代码如下:
// 三数取中
int GetMidIndex(int* arr, int begin, int end)
{int mid = (end - begin) / 2 + begin;if (arr[begin] < arr[end]){// begin < end < midif (arr[mid] > arr[end]){return end;}// mid < begin < endelse if (arr[mid] < arr[begin]){return begin;}// begin < mid < endelse{return mid;}}// end < beginelse{// mid < end < beginif (arr[mid] < arr[end]){return end;}//end < begin < midelse if(arr[mid] > arr[begin]){return begin;}else{return mid;}}
}
3.使用方法
在取key值时仍可继续取left位置的值,但是在此之前做一次交换即可。
int index = GetMidIndex(arr, begin, end);swap(&arr[index], &arr[left]);int key = arr[left];
总结
抓住快排的思想要点,加上调试即可快速实现出排序算法。
相关文章:
【排序】快速排序实现
目录 一、快速排序是什么? 二、左右指针法 1.实现原理 2.代码如下: 三、挖坑法 1.实现原理 2.代码如下: 四、前后指针法 1.实现原理 2.代码如下: 五、三数取中 1.实现思想 2.代码如下: 3.使用方法 总结…...
YOLOv5/v7 Flask Web 车牌识别 | YOLOv7 + EasyOCR 实现车牌识别
YOLOv7 Flask Web 车牌识别图片效果展示 本篇博文只包含源码以及使用方式,目前不同提供详细开发教程。 YOLOv7 Flask Web 车牌识别视频效果展示 YOLOv7 + EasyOCR 实现车牌识别 什么是Flask? 简介 Flask是一个轻量级的可定制框架,使用Python语言编写,较其他同类型框架更…...
【Opencv实战】几十年前的Vlog火了:黑白老照片如何上色?这黑科技操作一定要知道,复原度超高,竟美的出奇~(图像修复神级代码)
导语 哈喽大家好呀!我是每天疯狂赶代码的木木子吖~情人节快乐呀! 所有文章完整的素材源码都在👇👇 粉丝白嫖源码福利,请移步至CSDN社区或文末公众hao即可免费。 我们都知道,有很多经典的老照片…...
React源码分析(一)Fiber
前言 本次React源码参考版本为17.0.3。 React架构前世今生 查阅文档了解到, React16.x是个分水岭。 React15及之前 在16之前,React架构大致可以分为两层: Reconciler: 主要职责是对比查找更新前后的变化的组件;R…...
小樽 C++指针—— (壹) 指针变量
(壹) 指针变量 一、指针的概念与定义 二、给指针变量p赋值 三、指针变量的的、-运算 四、无类型指针 五、多重指针 C (壹) 指针变量 小明想把从李华家借来的书——《CCF中学生计算机程序设计》还给李华,但李华不在家,于是把书放到书架第3层的最右边…...
java 代码块 万字详解
概述 : 特点 : 格式 : 情景 : 细节 : 演示 : 英文 : //v,新版编辑器无手动添加目录的功能,PC端阅读建议通过侧边栏进行目录跳转;移动端建议用PC端阅读。😂一、概述 :代码块,也称为初始化块,属于类中的成员&…...
杂项-图片隐写
图片隐写的常见隐写方法: 三基色:RGB(Red Green Blue) 图片文件隐写 1.Firework 使用winhex打开文件时会看到文件头部中包含firework的标识,通过firework可以找到隐藏图片。 使用场景:查看隐写的图片文件…...
【高性价比】初学者入门吉他值得推荐购买的民谣单板吉他品牌—VEAZEN费森吉他
“在未知的世界里,我们是一群不疲不倦的行者,执念于真善美,热衷于事物的极致。我们抽丝剥茧,不断地打败自己,超越自己,我们无所畏惧终将成为巨人。”这是VEAZEN吉他官网首页上很明显的一段话,也…...
2023年浙江交安安全员考试题库及答案
百分百题库提供交安安全员考试试题、交安安全员考试真题、交安安全员证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 50.根据《建设工程安全生产管理条例》第65条规定,施工单位有下列()行…...
【新】华为OD机试 - 跳格子(Python)
跳格子 题目 地上共有 N 个格子,你需要跳完地上所有的格子, 但是格子间是有强依赖关系的,跳完前一个格子后, 后续的格子才会被开启,格子间的依赖关系由多组 steps 数组给出, steps[0] 表示前一个格子, steps[1] 表示 steps[0] 可以开启的格子: 比如 [0,1] 表示从跳完第…...
乡村能做社区团购吗?怎么做?我走访调查后发现机会很大
乡村能做社区团购吗?怎么做?我走访调查后发现机会很大#深度触网 #社区团购 #乡村振兴##乡村旅游##县域经济##市场经济##农文旅产业振兴研究院#乡村旅游能带动农产品加工业、服务业、商贸业等相关联产业的发展 乡村能做社区团购吗?怎么做&…...
态路小课堂丨下一代数据中心100G接口第二篇——SFP-DD封装
100G光模块根据封装模式可分为QSFP28、CXP、CFP、CFP2、FCP4、DSFP和SFP-DD等。态路小课堂之前已经大量介绍了相关内容(。 态路小课堂丨下一代数据中心100G接口——DSFP态路小课堂丨100G解决方案-425G NRZ光模块态路小课堂丨什么是100G QSFP28单波光模块?…...
状态栏和导航栏高度获取
/*** 获取导航栏高度*/public static int getNavigationBarHeight(Context context){int navigationBarHeight 0;int resourceId context.getResources().getIdentifier("navigation_bar_height", "dimen", "android")if (resourceId > 0) {…...
插曲:第一桶金 1w 的来由
因为前天跟同事聊天,发现有个比较严重的认知,就是关于赚钱思维。 同事反馈说工作十来年,却没有接过私活,这里话分两头,有可能私 活钱少,但他给我的理由是:私活太麻烦,有时候不敢接&a…...
中国甲基异丁基甲醇行业头部企业市场占有率及排名调研报告
内容摘要 本文调研和分析全球甲基异丁基甲醇发展现状及未来趋势,核心内容如下: (1)全球市场总体规模,分别按销量和按收入进行了统计分析,历史数据2018-2022年,预测数据2023至2029年。 …...
streamlit自定义组件教程和组件开发环境配置
About create your own component: you can follow this tutorial streamlit tutorial 重要!以下步骤都是在教程的基础上更改的。这个教程做的很棒。 Component development environment configuration: 根据文章 https://streamlit-com…...
Windows CMD常用命令
目录 【打开CMD命令】 【网络测试命令】 ipconfig------查看本机网卡信息 ping------测试网络是否通畅 tracert------追踪路由,也可以用来查看网络连通性 telnet------查看目的主机ip的端口号是否开放 tcping------查看目的主机ip的端口号是否开放 【关于路…...
ChIP-seq 分析:数据比对(3)
读取 reads(二者含义相同,下文不做区分)1. ChIPseq reads 比对 在评估读取质量和我们应用的任何读取过滤之后,我们将希望将我们的读取与基因组对齐,以便识别任何基因组位置显示比对读取高于背景的富集。 由于 ChIPseq…...
并非从0开始的c++之旅 day2
并非从0开始的c之旅 day2一、变量1、 变量名的本质二、程序的内存分区模型1、内存分区运行之前运行之后三、栈区注意事项四、堆区1、堆区使用2、堆区注意事项五、全局变量静态变量1、静态变量2、全局变量六、常量1、全局const常量2、局部const常量七、字符串常量一、变量 既能…...
Linux进阶(Shell编程学习一)
由于shell脚本在java项目运维方面极其重要,比如服务的启动脚本,日志的分割脚本,文件的管理脚本大多都是shell脚本去实现的。所以作为java开发者懂linux的基本命令,会基本的shell编程是必要的。 Shell 是一个用 C 语言编写的程序&…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
