快排(前后指针实现)

02f9ea45b5174b05b8ad7dad4f45fe9d.png

前言

快排解决办法有很多种,这里我再拿出来一种前后指针版本

虽然这个版本的时间复杂度和霍尔一样,逻辑也差不多,但是实际排序过程,确实会比霍尔慢一点

快排gif

b3d521cc988c4a3193d21d0c0e3e8b5a.gif

快排前后指针实现逻辑:

前后指针实现逻辑(升序):
单趟排序:
1,我们使用递归来进行实现,所以我们先实现单趟排序
2,定义两个下标,也就是所谓的指针,初始的时候,一个指向最左边第一个元素(prev),一个指向第二个元素(cur),最后定义一个对比keyi3,此时先判断我们的cur是不是小于keyi。cur小于keyi的话:prev++,交换,之后cur++4,但是我们如果和自己交换此时没有什么意义,所以这里我们需要做一个处理
5,继续往前走,如果遇见的是:比keyi下标大的元素此时,cur++,直到遇见的是比keyi下标小的元素,循环执行.prev++,交换,之后cur++

6,最后cur走到最后一个元素,我们交换keyi的下标元素和prev的下标元素

多趟实现:
1,递归进行分割:【left,keyi-1】keyi【keyi+1,right】
2,停止条件就是当left>=right
原因:【left, keyi-1】keyi【keyi+1, right】

07b544bcff274870887ae4d9edb5c0a3.png

快排单趟实现

这里只是图解单趟实现逻辑,因为多趟实现的逻辑和霍尔的一样,也是递归,所以不进行多次书写

c09ef1f8aec043a7bdcfa20e170442b0.png

代码实现

这里的代码实现的核心逻辑不一样,大的框架是一样的,也就是三数取中,以及减少递归从而使用插入排序这样的逻辑是一样的,下面我们来看看这个新的组装怪

//快排(前后指针方法)(递归实现)
void QuickSort02(int* a, int left, int right)
{
	//递归停止条件
	if (left >= right)
		return;
	//创建两个变量,作为前后指针使用
	int prev = left; int cur = prev + 1;
	int keyi = left;
	//当快指针到尾的时候,跳出循环->交换
	while (cur <= right)
	{
		//前后指针中间是比a[keyi]大的数值,所以遇见大的++,小的停止
		if (a[keyi] > a[cur])
		{
			//停止之后,慢指针++,并且进行交换,因为中间才是大的数值,cur遇见大数值++。遇见小数值才停下来
			prev++;
			Swap(&a[prev], &a[cur]);
			//同理快指针也进行++,往后移动
			cur++;
		}
		else
		{
			cur++;
		}
	}
	Swap(&a[prev], &a[keyi]);
	keyi = prev;
	//多趟递归实现
	//[left,keyi-1] keyi [keyi+1,right]   这里传递的是区间
	//  1     0      1     2      1       当只剩一个数值的时候,也就是这个区间的时候,递归停止 
	QuickSort02(a, left, keyi - 1);
	QuickSort02(a, keyi + 1, right);
}

总结:

  1. 算法基础:快速排序是一种分而治之的排序算法,它通过递归地将数组分为较小的子数组,然后对这些子数组进行排序。

  2. 分区策略:使用前后指针(prevcur)进行分区,而不是传统的左右指针。这种方法在某些情况下可以减少元素交换的次数。

  3. 基准值选择:基准值(keyi)是数组的第一个元素,即left索引对应的元素。

  4. 指针移动规则

    • prev作为慢指针,用于跟踪比基准值小的元素的边界。
    • cur作为快指针,从left + 1开始遍历数组。
  5. 元素交换:当快指针指向的元素大于基准值时,不进行交换,快指针继续移动;当快指针指向的元素小于或等于基准值时,与慢指针所指元素交换,然后慢指针和快指针都向前移动。

  6. 递归排序:在基准值确定之后,递归地对基准值左边和右边的子数组进行排序。

  7. 时间复杂度:平均情况下,快速排序的时间复杂度为O(n log n)。最坏情况下,如果每次分区都极不平衡,时间复杂度会退化到O(n^2)。

  8. 空间复杂度:由于递归性质,快速排序的空间复杂度为O(log n)。

  9. 算法优化:通过前后指针方法,可以在某些情况下提高快速排序的性能,特别是当基准值接近数组中间值时。

  10. 适用场景:快速排序适用于大多数需要排序的场景,特别是在大数据集上,它通常能够提供非常高效的排序性能。

优化

53718a8efe964eeb9fd6b68d66153777.png

这里我们可以看到,cur无论是if还是else里面都需要++,所以我们直接放到外面

其次我们为了效率,不和自己交换,我们不和自己交换,进行一个判断条件

快慢指针代码优化(完整)

//交换函数
void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
//快排(前后指针方法)(递归实现)
void QuickSort02(int* a, int left, int right)
{
	//递归停止条件
	if (left >= right)
		return;
	if (right - left + 1 >= 10)
	{
		InsertionSort(a + left, right - left + 1);
	}
	else
	{
		//三数取中
		int mid = GetMid(a, left, right);
		Swap(&a[mid], &a[left]);

		//单趟实现
		//创建两个变量,作为前后指针使用
		int prev = left; int cur = prev + 1;
		int keyi = left;
		//当快指针到尾的时候,跳出循环->交换
		while (cur <= right)
		{
			//前后指针中间是比a[keyi]大的数值,所以遇见大的++,小的停止
			if (a[keyi] > a[cur] && prev++ != cur)
			{
				//停止之后,慢指针++,并且进行交换,因为中间才是大的数值,cur遇见大数值++。遇见小数值才停下来
				Swap(&a[prev], &a[cur]);
			}
			cur++;
		}
		Swap(&a[prev], &a[keyi]);
		keyi = prev;
		//多趟递归实现
		//[left,keyi-1] keyi [keyi+1,right]   这里传递的是区间
		//  1     0      1     2      1       当只剩一个数值的时候,也就是这个区间的时候,递归停止 
		QuickSort02(a, left, keyi - 1);
		QuickSort02(a, keyi + 1, right);
	}
}

总结:

  1. 基本递归结构:算法使用递归调用来处理子数组,这是快速排序算法的核心结构。

  2. 小数组优化:当子数组的大小小于或等于10时,算法使用插入排序而不是快速排序,因为插入排序在小规模数据上更高效。

  3. 三数取中法:为了更均匀地分割数组,算法使用三数取中法选择基准值,这有助于减少最坏情况发生的概率。

  4. 前后指针方法:算法使用两个指针(prevcur),其中prev作为慢指针,cur作为快指针,通过这种方式进行一次遍历完成分区。

  5. 分区操作:快指针从left + 1开始遍历,如果当前元素小于基准值,则与慢指针所指的元素交换,然后慢指针向前移动。

  6. 递归排序子数组:基准值确定后,算法递归地对基准值左边和右边的子数组进行排序。

  7. 时间复杂度:平均情况下,算法的时间复杂度为O(n log n),最坏情况下为O(n^2)。但由于采用了小数组优化和三数取中法,最坏情况的发生概率降低。

  8. 空间复杂度:算法的空间复杂度为O(log n),这主要由于递归调用导致的栈空间使用。

  9. 适用场景:这种改进的快速排序算法适用于大多数需要排序的场景,尤其是在大数据集上,它能够提供非常高效的排序性能,同时在小数据集上也表现出较好的效率。

  10. 算法稳定性:由于使用了插入排序对小规模子数组进行排序,算法在处理小规模数据时具有稳定性。

  11. 注意:在实际测试·里面,前后指针比霍尔排序慢一点

通过这种混合排序策略,算法在保持快速排序优点的同时,也提高了在特定情况下的排序效率,使其成为一种更加健壮的排序方法。

注意事项

这里调用的插入排序是升序,写的快排也是升序,如果你需要测试降序,那么你需要把插入排序一起改成降序,不然会导致排序冲突

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

西瓜视频基于 Hertz 的微服务落地实践

# 1. 西瓜视频微服务架构设计 ## 1.1 西瓜视频介绍 **西瓜视频**是一个开眼界、涨知识的视频 App&#xff08;Informative Video Platform&#xff09;&#xff0c;作为国内领先的**中长视频**平台&#xff0c;它源源不断地为不同人群提供优质内容&#xff0c;让人们看到更丰…

从零开始搭建一个酷炫的个人博客

效果图 一、搭建网站 git和hexo准备 注册GitHub本地安装Git绑定GitHub并提交文件安装npm和hexo&#xff0c;并绑定github上的仓库注意&#xff1a;上述教程都是Windows系统&#xff0c;Mac系统会更简单&#xff01; 域名准备 购买域名&#xff0c;买的是腾讯云域名&#xf…

【web1】标签,css,js

文章目录 1.标签&#xff1a;input1.1 html&#xff1a;HTML&#xff08;用于创建网页结构&#xff09;&#xff0c;CSS&#xff08;对页面进行美化&#xff09;&#xff0c;JavaScript&#xff08;用于与用户交互&#xff09;1.2 文本标签&#xff1a;字体属性1.3 a标签&#…

win32API(CONSOLE 相关接口详解)

前言&#xff1a; Windows这个多作业系统除了协调应⽤程序的执⾏、分配内存、管理资源之外&#xff0c;它同时也是⼀个很⼤的服务中⼼&#xff0c;调⽤这个服务中⼼的各种服务&#xff08;每⼀种服务就是⼀个函数&#xff09;&#xff0c;可以帮应⽤程式达到开启视窗、描绘图形…

解析JSON字符串

QJsonDocument类用于解析JSON字符串&#xff0c;

android studio 模拟器文件查找

android studio 模拟器文件查找 使用安卓模拟器下载文件后通常无法在系统硬盘上找到下载的文件&#xff0c;安卓 studio studio 其实提供了文件浏览工具&#xff0c;找到后可以直接使用 Android studio 打开 打开 Android studioview 菜单view > Tool Windows > Device…

智慧校园的作用是什么?

在近几年&#xff0c;智慧校园以其独有的姿态&#xff0c;悄然改变着教育的面貌。想象一下&#xff0c;当物联网、大数据、人工智能这些前沿技术与传统校园深度融合&#xff0c;教育空间不再局限于实体教室&#xff0c;知识获取也不再受制于时间与地点&#xff0c;一个更加开放…

物联网系统运维——数据库部署,Linux环境下MySQL安装,使用phpMyAdmin管理MySQL,实验CentOS 7安装MySQL

一.MySQL 1.概要 MySQL是一种关联数据库管理系统&#xff0c;关联数据:而不是将所有数据放在一个大仓库内&#xff0c;这样就增加了速度并提高了灵活性库将数据保存在不同的表中。性能高、成本低、可靠性好&#xff0c;已经成为最流行的开源数据库。 二.MySQL安装与配置 1. …

P1223 排队接水

题目描述 有 &#x1d45b; 个人在一个水龙头前排队接水&#xff0c;假如每个人接水的时间为 &#x1d447;&#x1d456;&#xff0c;请编程找出这 &#x1d45b; 个人排队的一种顺序&#xff0c;使得 &#x1d45b;个人的平均等待时间最小。 输入格式 第一行为一个整数 &a…

python 字符串驻留机制

偶然发现一个python字符串的现象&#xff1a; >>> a 123_abc >>> b 123_abc >>> a is b True >>> c abc#123 >>> d abc#123 >>> c is d False 这是为什么呢&#xff0c;原来它们的id不一样。 >>> id(a)…

OOM日志分析

目录 1. 日志分析2. MAT 工具2.1 日志打印方式2.1.1 HeapDumpOnOutOfMemoryError&#xff08;推荐&#xff09;2.1.2 jmp 命令 2.2 MAT分析方式2.2.1 饼图分析2.2.2 树形图分析2.2.2 泄漏疑点 3. 优化 首先说一下结论&#xff1a;通过MAT工具分析才是最精准的&#xff0c;直接通…

Java程序之简单“记事本”

要求&#xff1a;如下图所示&#xff0c;记事本具有新建、打开文本、保存、关闭等功能。 算法思路&#xff1a; 这是一个使用Java Swing库创建的简单文本编辑器。它包含一个菜单栏&#xff0c;其中包含“文件”菜单以及四个子菜单项&#xff1a;“新建”、“打开”、“保存”和…

【Web APIs】DOM 文档对象模型 ⑤ ( 获取特殊元素 | 获取 html 元素 | 获取 body 元素 )

文章目录 一、获取特殊元素1、获取 html 元素2、获取 body 元素3、完整代码示例 本博客相关参考文档 : WebAPIs 参考文档 : https://developer.mozilla.org/zh-CN/docs/Web/APIgetElementById 函数参考文档 : https://developer.mozilla.org/zh-CN/docs/Web/API/Document/getE…

torchinfo这个包中的summary真的很好用

1.安装直接使用 pip 进行安装即可&#xff1a; pip install torchinfo 2.导入该模块 from torchinfo import summary 3.使用模块 summary(model)#这里的model是你自己的model&#xff0c;可以添加参数进去 4.效果图&#xff1a; 第一个图片是直接打印model吗&#xff0c;…

华为某员工爆料:三年前985本科起薪30万,现在硕士起薪还是30w,感慨互联网行情变化

“曾经的30万年薪&#xff0c;是985本科学历的‘标配’&#xff0c;如今硕士也只值这个价&#xff1f;” 一位华为员工的爆料&#xff0c;揭开了互联网行业薪资变化的冰山一角&#xff0c;也引发了不少人的焦虑&#xff1a;互联网人才“通货膨胀”的时代&#xff0c;真的结束了…

【docker1】指令,docker-compose,Dockerfile

文章目录 1.pull/image&#xff0c;run/ps&#xff08;进程&#xff09;&#xff0c;exec/commit2.save/load&#xff1a;docker save 镜像id&#xff0c;不是容器id3.docker-compose&#xff1a;多容器&#xff1a;宿主机&#xff08;eth0网卡&#xff09;安装docker会生成一…

【Git】win本地 git bash:Connect reset by 20.205.243.166 port22报错问题解决

win10 git bash 控制台 reset 22端口拒绝连接问题&#xff1a; Connection reset by 20.205.243.166 port 221、22端口 无法连接 ssh -T gitgithub.com2、尝试用443端口 仍然无法连接 ssh -T -P 443 gitgithub.com3、重写 git clone 地址 url&#xff0c;全局添加 https 前缀…

国产大模型技术创新分析

国产模型百舸争流&#xff0c;技术创新百花齐放 2023年下半年起&#xff0c;国内大模型领域迎来“百模大战”&#xff0c;各大厂商纷纷加速生成式AI的研发与突破&#xff0c;模型持续迭代升级&#xff0c;展现了人工智能技术的蓬勃发展与无限潜力。 中国大模型市场迅猛发展&am…

MapReduce程序设计2

要求 1、数据集stock-daily&#xff0c;包含A股近4000只股票的今年以来的日数据&#xff1b;数据集stock-daily-30d仅包含最近30个交易日数据&#xff0c;根据自己计算机性能选择。 数据来源&#xff1a;https://www.joinquant.com/help/api/help?nameJQData 2、数据集stoc…