【排序算法】C语言实现随机快排,巨详细讲解

请添加图片描述

文章目录

  • 🚀前言
  • 🚀快排的核心过程partition(划分过程)
  • 🚀快排1.0
  • 🚀随机快速排序
  • 🚀稳定性

🚀前言

铁子们好啊!继续我们排序算法今天要讲的是快排,通常大家所说的快排都是指随机快速排序,这里阿辉会详细的讲快排及其优化以及复杂度和稳定性的分析,话不多说开始我们今天的学习吧!!!

🚀快排的核心过程partition(划分过程)

在整个快排的过程中,快排最为核心的过程就是划分过程

划分过程:就是给定一个数作为划分值,将待划分的数组分成小于划分值的部分放在数组左边、等于划分值的部分在中间和大于划分值的部分在右边(为了方便,下文阿辉就直接简称为小于区、等于区和大于区)

对于划分过程是怎么样的思路呢?
对于一个数组的划分,我们需要三个指针来控制整个划分过程
用指针i来控制整个数组的遍历,用指针left来管理小于区域,用指针right来管理大于区域
请添加图片描述
假设我们取3作为划分值,i从左向右遍历数组,要分三种情况:

  • i指向的元素小于划分值时,i指向的数要与left指向的数字交换,然后++i同时++left
  • i指向的元素大于划分值时,i指向的数要与right指向的数字交换,然后--righti不变
  • i指向的元素等于划分值时,仅有i自增

为什么这么设计呢?
left控制着小于区,在left左边的元素都属于小于区;right控制着大于区,在right的右边的元素都属于大于区,而等于区的左边界是left右边界是rightleftright自身以及他们俩之间的元素都属于等于区。
++left代表小于划分值的元素发货到小于区,--right代表大于划分值的元素发货到大于区。为什么发货到小于区++i因为i是从左向右遍历的,left的数换到i位置不需要再看一遍了,而发货到大于区的时候,right的数换到i位置还没有看过,还得再看一遍它该发货到哪个区域。
对于上面的数组划分完是下面这样的:
请添加图片描述
让数组这样划分成这样后,对于中间的等于区域就不需要在管了,因为就算排好序它也应该在这个位置,前面都是小于它的后面都是大于大于它的,你说它是不是该在这!!!
附上partition函数的代码:

void partition(int a[],int l,int r,int x){//划分函数//l是待划分区域左边界,r是待划分过程右边界,x是划分值int i = l;//遍历偏移量while(i <= end){//i>end时说明要划分的区域已经划分完成if(a[i] == x){//遇到等于区域数不用管,i直接遍历下一位置++i;}else if(a[i] < x){//遇到小于区域数,发货到小于区域swap(a[i++],a[l++]);//l、i同时去到下一个位置}else{//遇到大于区域数发货到大于区域swap(a[i],a[r--]);//r同时去到下一位置}}}

划分过程是O(N)的时间复杂度,因为划分过程会遍历数组整个元素,跳出循环的条件是i>r,在每一次循环过程中都是i++或者--r,所以时间复杂度是O(N)

🚀快排1.0

有了上面的划分过程,就好办了,请出我们的老伙计——递归,当我们对于原数组等于区排好了,我们给原数组小于区域和大于区再次划分然后递归下去,递归到数组只有1个元素时数组天然有序作为我们的base case也就是递归的限制条件。
现在我们的重心就是要选定划分值,但是对于固定流程的程序,我们一定可以找到让这个程序最难受的数据状况,比如数组中只有1~9这9个元素,如果我们划分值选在数组最右的元素,对于下面这个数组
请添加图片描述
我们每次都会选到数组最大的元素,导致没有大于区域,而且一次递归只能排好一个位置的数,对于划分过程partition函数的时间复杂度是O(N),然后每次待排序数组递减,明显和冒泡、插入一个级别的O(N2)的时间复杂度,也就是说快排1.0的时间复杂度是O(N2)
代码:

  int begin,end;void quicksort(int a[],int l,int r){//快排主逻辑if(l >= r) return;//base case终止条件int x = a[r];//以数组最右元素作为划分值partition(a,l,r,x);//给数组根据随机出的划分值,做划分//用临时变量捕捉当前的边界,全局变量会被子递归过程更改int left = begin;int right = end;quicksort(a,l,left - 1);//左部分递归quicksort(a,right + 1,r);//右部分递归}void partition(int a[],int l,int r,int x){//划分函数//l是划分区域左边界,r是划分过程右边界begin = l;//全局变量记录等于区域左边界end = r;//全局变量记录等于区域右边界int i = l;//遍历偏移量while(i <= end){//i>end时说明要划分的区域已经划分完成if(a[i] == x){//遇到等于区域数不用管,i直接遍历下一位置++i;}else if(a[i] < x){//遇到小于区域数,发货到小于区域swap(a[i++],a[begin++]);//begin、i同时去到下一个位置}else{//遇到大于区域数发货到大于区域swap(a[i],a[end--]);//end、i同时去到下一位置}}}

我们想要的是O(NlogN)的快排,可不是这个和三大最挫排序一样效率的排序,好,让我们见识一下全盛时期的快排吧!!!

🚀随机快速排序

其实随机快排就比上面的快排1.0只换了一行代码,就让快拍的时间复杂度达到了O(NlogN)
代码:

  int begin,end;void quicksort(vector<int>& a,int l,int r){//快排主逻辑if(l >= r) return;//base case终止条件int x = a[l + rand() % (r - l + 1)];//随机一个划分值partition(a,l,r,x);//给数组根据随机出的划分值,做划分//用临时变量捕捉当前的边界,全局变量会被子递归过程更改int left = begin;int right = end;quicksort(a,l,left - 1);//左部分递归quicksort(a,right + 1,r);//右部分递归}void partition(vector<int>& a,int l,int r,int x){//划分函数//l是划分区域左边界,r是划分过程右边界begin = l;//全局变量记录等于区域左边界end = r;//全局变量记录等于区域右边界int i = l;//遍历偏移量while(i <= end){//i>end时说明要划分的区域已经划分完成if(a[i] == x){//遇到等于区域数不用管,i直接遍历下一位置++i;}else if(a[i] < x){//遇到小于区域数,发货到小于区域swap(a[i++],a[begin++]);//begin、i同时去到下一个位置}else{//遇到大于区域数发货到大于区域swap(a[i],a[end--]);//end、i同时去到下一位置}}}

就改了对与划分值的选取,用了随机的方式,在数组中随机选取一个元素作为划分值,随机快速排序的时间复杂度是O(NlogN),这里是为什么呢,阿辉也只是记住,并不知道原理,这是数学家把每一种结果的概率都求出来,然后算出期望,随机快排的时间复杂度收敛于O(NlogN),在算法导论上有证明,感兴趣的小伙伴可以去研究

🚀稳定性

随机快排是没有稳定性的,换句话说是划分过程没有稳定性,比如:
请添加图片描述
对于这样的数组,i位置与right一换,最后位置的2一下子跨越他前面那么多2,所以快排没有稳定性,但是快排比归并以及堆排序都快,是常数时间上快


请添加图片描述

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

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

相关文章

房产信息网源码,房产系统,二手房小程序源码,租房小程序系统楼盘系统房产经纪人系统

房产门户系统、多城市房产网、房产小程序 房产网系统、地方房产门户信息网 带im即时通讯聊天 二手房 租房 楼盘 置业顾问 经纪人 腾房云房产网 分为单城市版本 和多城市版本 多城市 自动定位当前城市 每个分站对应独立管理员分站管理 thinkphpuniapp 独立开源

微信开发者工具 git 拉取 failed invalid authentication scheme

微信开发者工具 git 拉取 failed invalid authentication scheme 拉取代码时报错,无效身份认证 解决方案: 1.检查git地址是否正常 2.检查git用户名密码是否正确

uniapp多格式文件选择(APP,H5)

uniapp多格式文件选择&#xff08;APP&#xff0c;H5&#xff09; 背景实现代码实现运行结果注意事项 尾巴 背景 从手机选择文件进行上传是移动端很常见的需求&#xff0c;在原生开发时由于平台专一性很容易实现。但是用uniapp开发官方提供的API在APP平台只能选择图片和视频&a…

使用visual studio写一个简单的c语言程序

官网下载visual studio&#xff0c;社区版免费的 https://visualstudio.microsoft.com/zh-hans/ 下载好以后选择自己的需求进行安装&#xff0c;我选择了两个&#xff0c;剩下的是默认。 创建文件&#xff1a;

K8s 安装部署-Master和Minion(Node)

K8s 安装部署-Master和Minion(Node) 操作系统版本&#xff1a;CentOS 7.4 Master &#xff1a;172.20.26.167 Minion-1&#xff1a;172.20.26.198 Minion-2&#xff1a;172.20.26.210&#xff08;后增加节点&#xff09; ETCD&#xff1a;172.20.27.218 先安装部署ETCD y…

第16章_网络编程(网络通信要素,TCP与UDP协议,网络编程API,TCP网络编程,UDP网络编程,URL编程)

文章目录 第16章_网络编程本章专题与脉络1. 网络编程概述1.1 软件架构1.2 网络基础 2. 网络通信要素2.1 如何实现网络中的主机互相通信2.2 通信要素一&#xff1a;IP地址和域名2.2.1 IP地址2.2.2 域名 2.3 通信要素二&#xff1a;端口号2.4 通信要素三&#xff1a;网络通信协议…

计算机网络_1.2因特网概述

1.2因特网概述 一、网络、互联网与因特网的区别与联系1、网络2、互联网3、因特网4、 互联网与因特网辨析 二、因特网介绍1、因特网发展的三个阶段2、因特网简介&#xff08;1&#xff09;因特网服务提供者&#xff08;ISP&#xff09;&#xff08;2&#xff09;因特网已经发展成…

大数据学习之Redis,十大数据类型的具体应用(一)

目录 3. 数据类型命令及落地应用 3.1 备注 3.2 Redis字符串&#xff08;String&#xff09; 单值单value 多值操作 获取指定区间范围内的值 数值增减 获取字符串长度和内容追加 分布式锁 getset(先get后set) 3.3 Redis列表&#xff08;List&#xff09; 简单说明 …

使用企业微信一年要花费多少钱?

从今天开始&#xff0c;大力将为大家呈现一个新的话题——“企微问答”&#xff0c;大家有什么问题可以回复我们的公众号&#xff0c;如果你是严肃认真的提问&#xff0c;我们会严肃认真的给你一个答案。今日问题 &#xff1a;用企业微信一年要花多少钱 使用企业微信要花多少钱…

BL808学习日志-3-DPI-RGB屏幕使用-LVGL D0

一、DPI-RGB驱动 BL808的手册上显示是支持RGB565屏幕显示输出的&#xff0c;但是一直没找到网上的使用例程。且官方的SDK显示也是能够使用的&#xff0c;只是缺少了驱动。这一部分驱动在SIPEED的SDK中已经内置了&#xff0c;今天就是简单的点亮一个800*480 RGB565的屏幕。 二、…

Elasticsearch Windows版安装配置

Elasticsearch简介 Elasticsearch是一个开源的搜索文献的引擎&#xff0c;大概含义就是你通过Rest请求告诉它关键字&#xff0c;他给你返回对应的内容&#xff0c;就这么简单。 Elasticsearch封装了Lucene&#xff0c;Lucene是apache软件基金会一个开放源代码的全文检索引擎工…

git push后,如何撤销git log上的错误注释

修改了本地的代码&#xff0c;执行了下面的操作&#xff0c;提交之后&#xff0c;怎么样修改 git add ********(文件名)//git add 添加修改文件名之后 git commit //git commit 在当前分支提交&#xff0c;编写提交注释 git push //git push 提交修…

Ubuntu 22.04安装Nginx负载均衡

君衍. 一、编译安装Nginx二、轮询算法实现负载均衡三、加权轮询算法实现负载均衡四、ip_hash实现负载均衡 一、编译安装Nginx 这里我们先将环境准备好&#xff0c;我使用的是Ubuntu22.04操作系统&#xff1a; 这个是我刚安装好的&#xff0c;所以首先我们进行保存快照防止安装…

[足式机器人]Part3 机构运动学与动力学分析与建模 Ch01-2 完整定常系统——杆组RRR

机械原理/机构简图/机构运动学推导/Kmtool.pkg 曲柄滑块机构运动学,五杆机构运动学,七杆机构运动学 本文仅供学习使用,总结很多本现有讲述运动学或动力学书籍后的总结,从矢量的角度进行分析,方法比较传统,但更易理解,并且现有的看似抽象方法,两者本质上并无不同。 2024…

考研高数(共轭根式)

1.定义 共轭根式&#xff1a;是指两个不等于零的根式A、B&#xff0c;若它们的积AB不含根式&#xff0c;则称A、B互为共轭根式。 共轭根式的一个显著特点是通过相乘能把根号去掉&#xff0c;这是很有帮助的 2.常用的共轭根式 3.例题 1&#xff09;求极限 2&#xff09;证明…

【大数据】详解 Flink 中的 WaterMark

详解 Flink 中的 WaterMark 1.基础概念1.1 流处理1.2 乱序1.3 窗口及其生命周期1.4 Keyed vs Non-Keyed1.5 Flink 中的时间 2.Watermark2.1 案例一2.2 案例二2.3 如何设置最大乱序时间2.4 延迟数据重定向 3.在 DDL 中的定义3.1 事件时间3.2 处理时间 1.基础概念 1.1 流处理 流…

C++数据结构与算法——数组

C第二阶段——数据结构和算法&#xff0c;之前学过一点点数据结构&#xff0c;当时是基于Python来学习的&#xff0c;现在基于C查漏补缺&#xff0c;尤其是树的部分。这一部分计划一个月&#xff0c;主要利用代码随想录来学习&#xff0c;刷题使用力扣网站&#xff0c;不定时更…

Linux系列之查看cpu、内存、磁盘使用情况

查看磁盘空间 df命令用于显示磁盘分区上的可使用的磁盘空间。默认显示单位为KB。可以利用该命令来获取硬盘被占用了多少空间&#xff0c;目前还剩下多少空间等信息。使用df -h命令&#xff0c;加个-h参数是为了显示GB MB KB单位&#xff0c;这样更容易查看 Filesystem …

【3DGS】从新视角合成到3D Gaussian Splatting

文章目录 引言&#xff1a;什么是新视角合成任务定义一般步骤NeRF的做法NeRF的三维重建NeRF的渲染 3DGS的三维重建从一组图片估计点云高斯点云模型球谐函数参数优化损失函数和协方差矩阵的优化高斯点的数量控制(Adaptive Density Control)新的问题 3DGS的渲染&#xff1a;快速可…

【行业应用-智慧零售】东胜物联餐饮门店智能叫号解决方案,为企业智能化升级管理服务

随着科技的不断进步&#xff0c;物联网设备已经广泛应用于各行各业&#xff0c;包括餐饮业。在餐饮门店的线下运营过程中&#xff0c;叫号系统是一项重要的设备需求。传统的叫号方式往往会消耗大量的人力和时间&#xff0c;而物联网技术为餐饮行业提供了一种更高效、智能化的解…