当前位置: 首页 > news >正文

快速排序三种思路详解!

一、快速排序的介绍

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中 的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右 子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。(其时间复杂度最优为N*logN,空间复杂度最优为lonN,这里就不予证明了!过程相当复杂!)

用一种通俗的话来讲快速排序其实就时设定一个界定值,然后分别开始遍历需要排序的元素,将小于该界定值和大于该界定值的放在其两侧,每次结束都能将该界定值放到其最终正确的位置!


二、快速排序的思想

快速排序其思想也是采用了分治的思想,将一个大问题转化为若干个小问题,然后逐个解决每个小问题,最终达到解决问题的目的!


三、快速排序的实现

由上面内容可以知道,若想实现快速排序,则可以先执行单个元素的排序,然后再进行递归处理解决整组数据的排序!因为快速排序是一种二叉树结构的交换排序,所以可以采用递归的方法将其解决!

 

下面来看一下如何实现单趟排序,让数据中一个元素位于其最终应处于的位置!

单趟排序的实现

注:本篇文章例子是以默认排升序,若要实现降序仅需要将循环条件改变一下即可!

法一:(霍尔思想)

其单趟排序的思想就是假定一个界定值,然后左右两边开始遍历,若要排升序,则左边找到的比界定值大的值就停下,右边找到比界定值小的就停下,然后交换两者的值,当左右两边相遇时,就结束循环,最后将相遇的位置的值与界定值交换位置即可完成本次界定值的最终位置的实现!

//注意:因为这是单趟排序,保证了界定值处于该数据最终所在的位置,所以该函数应返回本次界定值的位置,方便下次调用这个函数实现递归调用解决其另外界定值最终的位置!

画个图来形象的描述一下该过程是如何实现的吧!

代码如下:

int Hoare(int* a, int left,int right)
{int vali = left;while (left < right){//若没有left<right这个限制条件,那么当从左边开始走的时候其对应的值一直小于a[vali]时,则会导致越界问题!//注意若选取vali在左边,那么从右边先走,因为从右边先走才能保证最后相遇的位置一定是小于vali的值,因为从右边找//的话是找比val小于或等于的值停下来!while (left < right && a[right] >= a[vali]){right--;}while (left < right && a[left] <= a[vali]){left++;}swap(&a[left], &a[right]);}//因为最后left和right相遇,所以只需将a[vali]与二者任意一个交换位置即可!swap(&a[left], &a[vali]);return left;
}

注意:(1)该函数的实现需要注意的是,必须保证里面的循环条件是left<right,因为假设当从左边开始时,其后面的值一直小于等于val时,则会导致left越界,进而导致程序错误!

(2)还需要注意一点的是,当选的界定值在左边时,那么必须从右边开始遍历,因为从右边先走可以保证最终左边相遇右边时,其遇到的右边一定是小于val的值,因为当最后左边和右边相遇时,还需要交换左边或右边的值与val的值,若交换的值大于val时,交换之后则没有排序成功,反之,若选的界定值在右边时,那么必须从左边开始遍历,原理同上!

法二(挖坑大法!)

原理如下:挖坑大法的原理就是选定一个界定值,将其保存起来,然后将其位置假设为一个坑,然后左右两边分别开始遍历,当左边找到比界定值大的值时,则将其数据填入坑中,坑的位置更新为新填入数据原来的位置,当右边位置找到比界定值小的值时,也将其数据填入坑中,坑的位置更新为新填入数据原来的位置!最后当左右相遇时,它们相遇一定是在坑中相遇,将原来界定值存放到坑中,此时界定值与其左右两边数据保持相对有序!图像如下:

注:这里假定坑位为左边第一个数据!那么就必须从右边开始先遍历,原因与法一相同!

 

 

代码如下:

int hole (int* a, int left, int right)
{int hole = left;int val = a[left];while (left < right){//先从右边开始找比val小的值,找到后把坑填了,然后其位置就成为新的坑位!while (left < right && a[right] >= val){right--;}a[hole ] = a[right];hole = right;while (left < right && a[left] <= val){left++;}a[hole ] = a[left];hole = left;}a[hole ] = val;return left;
}

 法三:双指针

原理:定义两个快慢指针,当快指针指向的值小于界定值时,让慢指针向后走一步,然后交换快慢指针对应的值,不管如何快指针是都要向后走的,只有当快指针的值小于val时,慢指针才会向后走一步,然后与其值交换!最后当快指针走完整个数据循环结束!从其思想上面可以看出,当快慢指针之间的值都是比界定值大的数据,因为只有当指针指向的值小于界定值时,慢指针才会向后走,并与当前快指针指向的小于界定值的数据与前面的慢指针的值进行交换!

图像如下:

从图中可以看出,fast和slow之间的值都是大于界定值的!所以当fast找到比界定值小的数值后,进行slow++操作,然后交换二者位置,仍然可以保证 fast和slow之间的值还都是大于界定值!

代码如下:

int Dpointer(int* a, int left, int right)
{int slow = left;int fast = left + 1;int vali = left;while (fast<=right){if (fast!=++slow && a[fast] < a[vali])//当slow++的位置和fast位置相同时就没必要进行交换了!{slow++;swap(&a[fast], &a[slow]);}fast++;}//注意一定要交换slow当前的值与原vali的值,然后将vali的位置重新赋值为slow的位置!swap(&a[slow], &a[vali]);vali = slow;return vali;
}

以上三种方法都是单趟的排序,因为快排是一种二叉树结构的交换排序方法,所以要想将所有元素进行排序,就可以采用递归的方法进行操作,从而完成整组数据的排序!

整组数据的排序实现!

代码如下:

void Qsort(int* a, int left, int right)
{//控制当区间不存在时,则跳出递归!if (left >= right){return;}/*int vali = Hoare(a, left,right);*///int vali = hig(a, left,right);int vali = Dpointer(a, left, right);Qsort(a, left, vali - 1);Qsort(a, vali+1, right);
}

当第一个排过序后,其第一个界定值就处于其最终存在的位置,所以可将界定值左边的元素再次进行一次排序,从而找到下一个界定值最终处于的位置,直至最后所要排序的区间不存在,排序即完成!

 

今日的快排分享到此为止,如有小伙伴还有不懂的地方欢迎在评论区留言提问哦! 

 

 

 

相关文章:

快速排序三种思路详解!

一、快速排序的介绍 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法&#xff0c;其基本思想为&#xff1a;任取待排序元素序列中 的某元素作为基准值&#xff0c;按照该排序码将待排序集合分割成两子序列&#xff0c;左子序列中所有元素均小于基准值&#xff0c;…...

【二叉树入门指南】链式结构的实现

【二叉树入门指南】链式结构的实现 一、前置说明二、二叉树的遍历2.1前序遍历2.2中序遍历2.3 后序遍历 三、以前序遍历为例&#xff0c;递归图解四、层序遍历五、节点个数以及高度等5.1 二叉树节点个数5.2二叉树叶子节点个数5.3 二叉树第k层节点个数5.4 二叉树查找值为x的节点5…...

【位运算】算法实战

文章目录 一、算法原理常见的位运算总结 二、算法实战1. leetcode面试题01.01. 判断字符是否唯一2. leetcode268 丢失的数字3. leetcode371 两整数之和4. leetcode004 只出现一次的数字II5. leetcode面试题17.19. 消失的两个数字 三、总结 一、算法原理 计算机中的数据都以二进…...

C++构建系统

收集C构建系统(2023)&#xff1a; 跟我一起写Makefile (PDF重制版)CMake tutorialConan, software package manager for C and C developersvcpkg-repovcpkgGoogle Bazel Build System { Fast, Correct } — Choose twoGN gn_quick_start当前Chromium构建系统 GYP Generate You…...

“深入探索JVM内部机制:理解Java虚拟机的运行原理“

标题&#xff1a;深入探索JVM内部机制&#xff1a;理解Java虚拟机的运行原理 摘要&#xff1a;本篇博客将深入探索Java虚拟机&#xff08;JVM&#xff09;的内部机制&#xff0c;帮助读者理解JVM的运行原理。我们将介绍JVM的组成结构&#xff0c;包括类加载器、运行时数据区域…...

java八股文面试[JVM]——双亲委派模型

1.当AppClassLoader去加载一个class时&#xff0c;它首先不会自己去尝试加载这个类&#xff0c;而是把类加载请求委托给父加载器ExtClassLoader去完成。 2.当ExtClassLoader去加载一个class时&#xff0c;它首先也不会去尝试加载这个类&#xff0c;而是把类加载请求委托给父加载…...

NLP与大模型主题全国师资培训班落地,飞桨持续赋能AI人才培养

为了推动大模型及人工智能相关专业人员的培养&#xff0c;8月11日-8月13日&#xff0c;由中国计算机学会主办、机械工业出版社、北京航空航天大学、百度飞桨联合承办 “CCF群星计划之文心高校行- NLP与大模型”主题师资培训班&#xff08;以下简称培训班&#xff09;在北京天信…...

Jupyter Notebook 配置根目录

注&#xff1a;本文是在 Windows 10 上配置 Jupyter Notebook 打开的默认根目录&#xff0c;Linux 同。 步骤一&#xff1a;创建 Jupyter Notebook 配置文件 使用以下命令创建 Jupyter Notebook 配置文件&#xff08;如果尚未创建&#xff09;&#xff1a; jupyter notebook …...

算法 位运算

文章目录 一、&&#xff08;按位与&#xff09;运算符二、|&#xff08;按位或&#xff09;运算符三、^&#xff08;异或&#xff09;运算符四、~&#xff08;取反&#xff09;运算符五、<<&#xff08;左移&#xff09;运算符六、>>&#xff08;右移&#xff…...

Linux 虚拟机常用命令

一、文件/文件夹管理 1. ls命令 就是 list 的缩写&#xff0c;通过 ls 命令不仅可以查看 linux 文件夹包含的文件&#xff0c;而且可以查看文件权限(包括目录、文件夹、文件权限)查看目录信息等等。 ls -a 列出目录所有文件&#xff0c;包含以.开始的隐藏文件ls -A 列出除.…...

解决抖音semi-ui的Input无法获取到onChange事件

最近在使用semi-ui框架的Input实现一个上传文件功能时遇到了坑&#xff0c;就是无法获取到onChange事件&#xff0c;通过console查看只是拿到了一个文件名。但若是把<Input>换成原生的<input>&#xff0c;就可以正常获取到事件。仔细看了下官方文档&#xff0c;发现…...

免费的png打包plist工具CppTextu,一款把若干资源图片拼接为一张大图的免费工具

经常做游戏打包贴图的都知道&#xff0c;要把图片打包为一张或多张大图&#xff0c;要使用打包工具TexturePacker。 TexturePacker官方版可以直接导入PSD、SWF、PNG、BMP等常见的图片格式&#xff0c;主要用于网页、游戏和动画的制作&#xff0c;它可以将多个小图片汇聚成一个…...

深层次分析字符数组和字符串的区别是什么?

前言 &#xff08;1&#xff09;休闲时刻刷B站&#xff0c;看到一个卖课的&#xff0c;发视频问&#xff0c;char arr1[]{‘H’,‘E’,‘L’,‘L’,‘O’};和char arr2[]“HELLO”;区别是什么。 &#xff08;2&#xff09;看那个卖课博主一顿分析&#xff0c;最后成功得出&…...

Redis 的主从复制、哨兵模式、集群脑裂

主从复制 主从复制是 Redis 高可用服务最基础的保证&#xff0c;将一台 Redis 主服务器&#xff0c;同步数据到多台 Redis 从服务器上&#xff0c;即一主多从的模式&#xff0c;且主从服务器之间采用的是「读写分离」的方式。 主服务器可以进行读写操作&#xff0c;当发生写操…...

Pycharm通过SSH配置centos上Spark环境

直接在shell进行pyspark进行编程&#xff0c;程序没有办法写得太长&#xff0c;而且我们希望能够实现一个及时给出结果的编程环境&#xff0c;可以使用pycharm连接centos上的spark&#xff0c;进行本地编程&#xff0c;同步到centos系统中运行程序&#xff0c;并把结果返回pych…...

leetcode做题笔记98. 验证二叉搜索树

给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 思路一&#xff1a;递归 …...

C# 中Lambda中的的匿名函数

/// <summary>/// 根据设备号&#xff0c;获取故障列表/// </summary>/// <param name"scanCode">主键</param>/// <returns></returns>[HttpGet]public async Task<IActionResult> GetItemPageList(string scanCode){//v…...

铰接式车辆的横向动力学仿真提供车辆模型研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

Ubuntu20 安装 libreoffice

1 更新apt-get sudo apt-get update2 安装jdk 查看jdk安装情况 Command java not found, but can be installed with:sudo apt install default-jre # version 2:1.11-72, or sudo apt install openjdk-11-jre-headless # version 11.0.138-0ubuntu1~20.04 sud…...

HTTP协议(JavaEE初阶系列15)

目录 前言&#xff1a; 1.HTTP协议 1.1HTTP协议是什么 1.2HTTP协议的报文格式 1.2.1抓包工具的使用 1.2.2HTTP请求 1.2.3HTTP响应 2.HTTP请求 2.1首行的组成 2.2.1URL的组成 2.2认识“方法”&#xff08;method&#xff09; 2.2.1GET方法 2.2.2POST方法 2.2.3GET…...

机器学习基础10-审查回归算法(基于波士顿房价的数据集)

上一节介绍了如何审查分类算法&#xff0c;并介绍了六种不同的分类算法&#xff0c;还 用同一个数据集按照相同的方式对它们做了审查&#xff0c;本章将用相同的方式对回归算法进行审查。 在本节将学到&#xff1a; 如何审查机器学习的回归算法。如何审查四种线性分类算法。如…...

基于 CentOS 7 构建 LVS-DR 群集。配置nginx负载均衡。

1、基于 CentOS 7 构建 LVS-DR 群集。 [root132 ~]# nmcli c show NAME UUID TYPE DEVICE ens33 c89f4a1a-d61b-4f24-a260-6232c8be18dc ethernet ens33 [root132 ~]# nmcli c m ens33 ipv4.addresses 192.168.231.200/24 [r…...

【云原生】Docker的数据管理(数据卷、容器互联)

目录 一、数据卷&#xff08;容器与宿主机之间数据共享&#xff09; 二、数据卷容器&#xff08;容器与容器之间数据共享&#xff09; 三、 容器互联&#xff08;使用centos镜像&#xff09; 总结 用户在使用Docker的过程中&#xff0c;往往需要能查看容器内应用产生的数据…...

使用vlc在线播放rtsp视频url

1. 2. 3. 工具链接&#xff1a; https://download.csdn.net/download/qq_43560721/88249440...

copy is all you need前向绘图 和疑惑标记

疑惑的起因 简化前向图 GPT4解释 这段代码实现了一个神经网络模型&#xff0c;包含了BERT、GPT-2和MLP等模块。主要功能是给定一个文本序列和一个查询序列&#xff0c;预测查询序列中的起始和结束位置&#xff0c;使其对应文本序列中的一个短语。具体实现细节如下&#xff1a…...

【附安装包】Vred2023安装教程

软件下载 软件&#xff1a;Vred版本&#xff1a;2023语言&#xff1a;简体中文大小&#xff1a;2.39G安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.0GHz 内存4G(或更高&#xff09;下载通道①百度网盘丨64位下载链接&#xff1a;https://pan.baidu.com…...

ASP.NET Core 中的 Dependency injection

依赖注入&#xff08;Dependency Injection&#xff0c;简称DI&#xff09;是为了实现各个类之间的依赖的控制反转&#xff08;Inversion of Control&#xff0c;简称IoC &#xff09;。 ASP.NET Core 中的Controller 和 Service 或者其他类都支持依赖注入。 依赖注入术语中&a…...

优化物料编码规则,提升物料管理效率

导 读 ( 文/ 2358 ) 物料是生产过程的必需品。对物料进行身份的唯一标识&#xff0c;可以更好的管理物料库存、库位&#xff0c;更方便的对物料进行追溯。通过编码规则的设计&#xff0c;可以对物料按照不同的属性、类别或特征进行分类&#xff0c;从而更好地进行库存分析、计划…...

Jetbrains IDE新UI设置前进/后退导航键

背景 2023年6月&#xff0c;Jetbrains在新发布的IDE&#xff08;Idea、PyCharm等&#xff09;中开放了新UI选项&#xff0c;我们勾选后重启IDE&#xff0c;便可以使用这一魔性的UI界面了。 但是前进/后退这对常用的导航键却找不到了&#xff0c;以前的设置方式&#xff08;Vi…...

借助frp的xtcp+danted代理打通两边局域网p2p方式访问

最终效果 实现C内网所有设备借助c1内网代理访问B内网所有服务器 配置公网服务端A frps 配置frps.ini [common] # 绑定frp穿透使用的端口 bind_port 7000 # 使用token认证 authentication_method token token xxxx./frps -c frps.ini启动 配置service自启(可选) /etc/…...