学习数据结构(16)快速排序

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

1、递归版本

递归版本实现的主要框架:

void QuickSort(int* arr, int left, int right)
{if(left >= right){return;}int keyi = _QuickSort(arr, left, right);QuickSort(arr, left, keyi - 1);QuickSort(arr, keyi+1, right);
} 
(1)hoare方法

这个函数的作用在于将基准值移到数组正确的位置并返回此处的下标。

left从基准值后一个位置开始移动,当left<=right时进入循环,left循环向前移动找比基准值大的数据,找到跳出循环,left循环向后移动找比基准值小的数据,找到跳出循环,此时若left<=right,交换left和right的数据,right--,left++继续循环。直到left>right跳出循环,此时right所在的位置就是基准值的正确位置,交换keyi和right的数据,返回right。

int _QuickSort(int* arr, int left, int right)
{int keyi = left;++left;while (left <= right){while (left <= right&&arr[left] < arr[keyi]){++left;}while (left <= right && arr[right] > arr[keyi]){--right;}if (left <= right){swap(&arr[right--], &arr[left++]);}}swap(&arr[keyi], &arr[right]); return right;}

上面代码有一处需要注意:

以下图为例:

若存在数组中有很多个相同的值的情况,加等于号的代码会找到很多个相同的基准值,重复调用多次函数,而不加等于号的代码可以在一次函数调用中多次交换,避免无效的分割排序

(2)挖坑法

将left所在的位置看作坑,并设为基准值,将基准值用key保存下来,当left<right时进入循环,由于初始的坑在左侧,所以right先向后移动,找比基准值小的元素,找到后将right处的下标赋给hole,值也赋给hole,此时right所在的位置成为新的坑,再到left向后移动,找比基准值大的元素,找到后将left处的下标赋给hole,值也赋给hole,此时left所在的位置成为新的坑,继续循环。

跳出循环后,此时left和right和hole指向同一个位置,这个位置就是基准值的正确位置,将key赋给arr[hole],返回hole。

int _QuickSort1(int* arr, int left, int right)
{int hole = left;int key = arr[hole];while (left < right){while (left <right && arr[right] > arr[key]){--right;}arr[hole] = arr[right];hole = right;while (left <right && arr[left] < arr[key]){++left;}arr[hole] = arr[left];hole = left;}arr[hole] = key;return hole;
}
(3)lomuto前后指针

定义基准值为left所在的位置,把left赋给prev,cur为prev的后一个位置,当cur<=right时,进入循环,cur在前探路,找比基准值小的元素,若找到了则prev++,将prev和cur所在位置的元素对调,为了避免将同一个元素对调,可以将++prev加入到循环中,写成如下代码的形式。

跳出循环后,此时prev所在的位置就是基准值的正确位置,将arr[prev]和arr[keyi]对调,返回prev。

int _QuickSort2(int* arr, int left, int right)
{int keyi = left;int prev = left, cur = prev + 1;while (cur <= right){if (arr[keyi] > arr[cur] && ++prev != cur){swap(&arr[prev], &arr[cur]);}cur++;}swap(&arr[keyi], &arr[prev]);return prev;
}

2、非递归版本(用栈实现)

栈的作用在于保存需要排序的序列。先将数组头尾下标入栈,当栈不为空时进入循环,取两次栈顶元素分别赋给begin和end,取完后出栈,基准值为begin所在位置的元素,prev为begin所在位置cur为prev后一个元素的下标,prev与cur的作用与双指针法里的作用一样,找到基准值的正确位置后将prev赋给keyi,若keyi+1<end则将keyi和end作为新序列的头尾下标入栈,若begin<keyi-1则将begin和keyi-1作为新序列的头尾下标入栈,继续循环。

void QuickSortNonR(int* arr, int left, int right)
{ST st;STInit(&st);STPush(&st, right);STPush(&st, left);while (!STEmpty(&st)){int begin = STTop(&st);STPop(&st);int end = STTop(&st);STPop(&st);int keyi = begin;int prev = begin;int cur = prev + 1;while (cur <= end){if (arr[keyi] > arr[cur] && ++prev != cur){swap(&arr[prev], &arr[cur]);}cur++;}swap(&arr[keyi], &arr[prev]);keyi = prev;if (keyi + 1 < end){STPush(&st, end);STPush(&st, keyi+1);}if (begin < keyi-1){STPush(&st, keyi-1);STPush(&st, begin);}}STDestroy(&st);
}

快速排序的时间复杂度为O(n\log n)

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

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

相关文章

uni-app iOS 上架常见问题与解决方案,实战经验全解析

uni-app 让开发者能够“一套代码&#xff0c;多端运行”&#xff0c;极大降低了开发成本。 但当应用进入 iOS 上架阶段 时&#xff0c;不少团队发现流程并没有想象中那么顺利&#xff1a;证书问题、打包失败、上传出错、审核被拒……这些都可能让项目卡壳。 本文结合实际案例&a…

洗衣机的智能升级集成方案WT2606B屏幕驱动+AI语音控制

2025&#xff0c;洗衣机市场正从功能满足转向体验升级&#xff0c;企业正面临哪些转型难点?一文为您解读洗衣机行业智能化升级之路。传统洗衣机就像是一个"沉默的工人"&#xff0c;只能通过简单的LED指示灯告诉你它在工作&#xff0c;却无法让你真正了解它在干嘛。用…

机器学习进阶,梯度提升机(GBM)与XGBoost

梯度提升机&#xff08;Gradient Boosting Machine, GBM&#xff09;&#xff0c;特别是其现代高效实现——XGBoost。这是继随机森林后自然进阶的方向&#xff0c;也是当前结构化数据竞赛和工业界应用中最强大、最受欢迎的算法之一。为什么推荐XGBoost&#xff1f; 与随机森林互…

【ARMv7】开篇:掌握ARMv7架构Soc开发技能

本专栏&#xff0c;开始与大家共同总结使用ARMv7系列CPU的Soc开发技能。大概汇总了一下&#xff0c;后面再逐步完善下面的思维导图。简单说说&#xff1a;与通用的ARMv7-A/R相比&#xff0c;以STM32F为代表的ARMv7-M架构有以下关键区别和重点&#xff1a;无MMU&#xff0c;有MP…

【学术会议论文投稿】JavaScript在数据可视化领域的探索与实践

【ACM出版 | EI快检索 | 高录用】2024年智能医疗与可穿戴智能设备国际学术会议&#xff08;SHWID 2024&#xff09;_艾思科蓝_学术一站式服务平台 更多学术会议请看 学术会议-学术交流征稿-学术会议在线-艾思科蓝 目录 引言 JavaScript可视化库概览 D3.js基础入门 1. 引入…

CSS基础学习步骤

好的&#xff0c;这是一份为零基础初学者量身定制的 **CSS 学习基础详细步骤**。我们将从最根本的概念开始&#xff0c;通过一步一步的实践&#xff0c;带你稳稳地入门。 第一步&#xff1a;建立核心认知 - CSS 是做什么的&#xff1f; 1. 理解角色&#xff1a; HTML&…

MTK Linux DRM分析(三十七)- MTK phy-mtk-hdmi.c 和 phy-mtk-hdmi-mt8173.c

一、简介 HDMI PHY驱动 HDMI 的物理层接口主要就是 HDMI Type-A 接口(19 pin),除此之外还有 Type-B、Type-C(Mini HDMI)、Type-D(Micro HDMI)、Type-E(车载专用)。 1. HDMI Type-A(常见 19-pin 标准接口) HDMI Type-A Connector Pinout ========================…

【人工智能学习之MMdeploy部署踩坑总结】

【人工智能学习之MMdeploy部署踩坑总结】报错1&#xff1a;TRTNet: device must be a GPU!报错2&#xff1a;Failed to create Net backend: tensorrt报错3&#xff1a;Failed to load library libonnxruntime_providers_shared.so1. 确认库文件是否存在2. 重新安装 ONNX Runti…

力扣516 代码随想录Day16 第一题

找二叉树左下角的值class Solution { public:int maxd0;int result;void traversal(TreeNode* root,int depth){if(root->leftNULL&&root->rightNULL){if(depth>maxd){maxddepth;resultroot->val;}}if(root->left){depth;traversal(root->left,depth…

网格图--Day07--网格图DFS--LCP 63. 弹珠游戏,305. 岛屿数量 II,2061. 扫地机器人清扫过的空间个数,489. 扫地机器人,2852. 所有单元格的远离程度之和

网格图–Day07–网格图DFS–LCP 63. 弹珠游戏&#xff0c;305. 岛屿数量 II&#xff0c;2061. 扫地机器人清扫过的空间个数&#xff0c;489. 扫地机器人&#xff0c;2852. 所有单元格的远离程度之和 今天要训练的题目类型是&#xff1a;【网格图DFS】&#xff0c;题单来自灵茶山…

多功能修改电脑机器码序列号工具 绿色版

多功能修改电脑机器码序列号工具 绿色版电脑机器码序列号修改软件是一款非常使用的数据化虚拟修改工具。机器码修改软件可以虚拟的定制您电脑上的硬件信息&#xff0c;软件不会对您的电脑造成伤害。软件不需要您有专业的知识&#xff0c;就可以模拟一份硬件信息。机器码修改软…

React Hooks深度解析:useState、useEffect及自定义Hook最佳实践

React Hooks自16.8版本引入以来&#xff0c;彻底改变了我们编写React组件的方式。它们让函数组件拥有了状态管理和生命周期方法的能力&#xff0c;使代码更加简洁、可复用且易于测试。本文将深入探讨三个最重要的Hooks&#xff1a;useState、useEffect&#xff0c;以及如何创建…

期权平仓后权利金去哪了?

本文主要介绍期权平仓后权利金去哪了&#xff1f;期权平仓后权利金的去向需结合交易角色&#xff08;买方/卖方&#xff09;、平仓方式及市场价格变动综合分析&#xff0c;具体可拆解为以下逻辑链条。期权平仓后权利金去哪了&#xff1f;1. 买方平仓&#xff1a;权利金的“差价…

2025国赛C题题目及最新思路公布!

C 题 NIPT 的时点选择与胎儿的异常判 问题 1 试分析胎儿 Y 染色体浓度与孕妇的孕周数和 BMI 等指标的相关特性&#xff0c;给出相应的关系模 型&#xff0c;并检验其显著性。 思路1&#xff1a;针对附件中孕妇的 NIPT 数据&#xff0c;首先对数据进行预处理&#xff0c;并对多…

NLP技术爬取

“NLP技术爬取”这个词组并不指代一种单独的爬虫技术&#xff0c;而是指将自然语言处理&#xff08;NLP&#xff09;技术应用于网络爬虫的各个环节&#xff0c;以解决传统爬虫难以处理的问题&#xff0c;并从中挖掘出更深层次的价值。简单来说&#xff0c;它不是指“用NLP去爬”…

让录音变得清晰的软件:语音降噪AI模型与工具推荐

在数字内容创作日益普及的今天&#xff0c;无论是播客、线上课程、视频口播&#xff0c;还是远程会议&#xff0c;清晰的录音质量都是提升内容专业度和观众体验的关键因素之一。然而&#xff0c;由于环境噪音、设备限制等因素&#xff0c;录音中常常夹杂各种干扰声音。本文将介…

大话 IOT 技术(1) -- 架构篇

文章目录前言抛出问题现有条件初步设想HTTP 与 MQTT中间的服务端完整的链路测试的虚拟设备实现后话当你迷茫的时候&#xff0c;请点击 物联网目录大纲 快速查看前面的技术文章&#xff0c;相信你总能找到前行的方向 前言 Internet of Things (IoT) 就是物联网&#xff0c;万物…

【wpf】WPF 自定义控件绑定数据对象的最佳实践

WPF 自定义控件绑定数据对象的最佳实践&#xff1a;以 ImageView 为例 在 WPF 中开发自定义控件时&#xff0c;如何优雅地绑定数据对象&#xff0c;是一个经常遇到的问题。最近在实现一个自定义的 ImageView 控件时&#xff0c;我遇到了一个典型场景&#xff1a; 控件内部需要使…

[Dify 专栏] 如何通过 Prompt 在 Dify 中模拟 Persona:即便没有专属配置,也能让 AI 扮演角色

在 AI 应用开发中,“Persona(角色扮演)”常被视为塑造 AI 个性与专业边界的重要手段。然而,许多开发者在使用 Dify 时会疑惑:为什么我在 Chat 应用 / Agent 应用 / Workflow 里都找不到所谓的 Persona 配置项? 答案是:Dify 平台目前并没有内建的 Persona 配置入口。角色…

解决双向循环链表中对存储数据进行奇偶重排输出问题

1. 概念 对链表而言,双向均可遍历是最方便的,另外首尾相连循环遍历也可大大增加链表操作的便捷性。因此,双向循环链表,是在实际运用中是最常见的链表形态。 2. 基本操作 与普通的链表完全一致,双向循环链表虽然指针较多,但逻辑是完全一样。基本的操作包括: 节点设计 初…