【排序】快速排序实现
目录
一、快速排序是什么?
二、左右指针法
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 语言编写的程序&…...
ARMv8地址转换机制与TCR_EL2寄存器详解
1. ARMv8地址转换机制概述在ARMv8架构中,地址转换是连接虚拟地址空间和物理内存的核心机制。这种转换通过多级页表结构实现,允许操作系统和hypervisor灵活地管理内存资源。作为系统程序员,理解这个机制的工作原理对开发高效可靠的系统软件至关…...
《如果你还愿意等》的搜索理由:等待场景怎样被记住
从内容传播角度看,《如果你还愿意等》的优势在于语气。它不是命令,也不是苦情控诉,而是把等待放成一个“如果”:有余地,也有边界。这个标题能自然带出使用场景:未读消息、夜车灯光、异地关系、还没完全离开…...
自动驾驶语义观察层:VLM与量化优化实践
1. 自动驾驶中的语义观察层:为什么传统方法不够用?在自动驾驶领域,我们经常遇到一些"看起来不对劲"的场景——比如一辆运输卡车后部悬挂的交通信号灯(应该遵循还是忽略?)、道路上突然出现的瘪气皮…...
AI网关架构解析:统一管理多模型API,提升服务治理与性能
1. 项目概述:一个AI驱动的开源网关框架最近在开源社区里,我注意到一个名为hoazgazh/aigate的项目。这个名字乍一看有点神秘,但拆解一下,“aigate”直译就是“AI网关”。这立刻让我联想到当前技术领域的一个核心痛点:如…...
AIAgent服务降级总失效?用SITS2026定义的3类语义韧性指标重构你的容错策略
更多请点击: https://intelliparadigm.com 第一章:AIAgent服务降级失效的根源诊断 AIAgent 服务在高并发或依赖组件异常时,常配置熔断与降级策略,但实践中频繁出现降级逻辑未触发、兜底响应缺失或返回错误码而非预设友好内容等问…...
基于Simulink的异步电机恒压频比开环调速系统建模与性能分析
1. 异步电机恒压频比控制原理揭秘 我第一次接触恒压频比控制时,被这个专业名词吓到了,后来发现它的核心思想其实特别简单。想象一下开车时的油门踏板——踩得越深车速越快,但发动机的"力气"(扭矩)基本保持不…...
如何永久保存微信聊天记录?WeChatMsg开源工具让你的数字记忆永不丢失
如何永久保存微信聊天记录?WeChatMsg开源工具让你的数字记忆永不丢失 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Tre…...
Go语言技能树工具goskill:构建与管理技术团队知识图谱
1. 项目概述:一个Go语言技能树的构建与管理工具最近在整理团队内部的技术栈和成员技能时,发现了一个挺普遍的问题:我们很难清晰地知道谁擅长什么,某个技术方向(比如微服务、数据库优化)的深度如何ÿ…...
为团队统一开发环境使用TaotokenCLI一键配置
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 为团队统一开发环境使用TaotokenCLI一键配置 当技术团队开始将大模型能力集成到多个项目中时,一个常见的挑战是如何快速…...
3分钟快速指南:如何用VoiceFixer免费修复模糊语音录音
3分钟快速指南:如何用VoiceFixer免费修复模糊语音录音 【免费下载链接】voicefixer General Speech Restoration 项目地址: https://gitcode.com/gh_mirrors/vo/voicefixer 你是否曾为模糊不清的会议录音而烦恼?是否因为背景噪音导致重要对话无法…...
