【数据结构】快速排序(4种方式实现)

前言:前面我们学习了几种相对比较简单的排序,今天我们要一起学习的是快速排序,我们将通过四种方式来模拟实现快排。

💖 博主CSDN主页:卫卫卫的个人主页 💞
👉 专栏分类:数据结构 👈
💯代码仓库:卫卫周大胖的学习日记💫
💪关注博主和博主一起学习!一起努力!
在这里插入图片描述


C语言算法-快速排序

什么是快速排序

任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

快速排序之hoare版

hoare思想

1.首先我们选定一个基准值,通常是数组中的第一个元素。
2. 定义俩个指针,一个left一个right分别在数组的最左边和最右边。
3. 我们让右指针先走,如果比我们定义的基准值小就停下来。
4. 右指针走完我们在让左指针走,如果比我们定义的基准值小也停下来。
5. 在俩个指针都停下来的时候把它们的值进行交换,以此反复循环直到俩个指针相遇,我们把基准值和它们的值进行交换。
6. 最终这一趟下来我们会得到如下图一样的数据,基准值左边的都比基准值小,右边的都比基准值大。
7. 我们把这一趟走完后在重新分为左右俩个部分的数据,在用此方法以此往复即可实现一个有序数组。

请添加图片描述
代码思路:刚刚我们用那个思想可以实现一次的排序过程,可是排完一次那剩下的怎么排呢?我们可以把这个问题拆成许多个小问题(如下图所示),因此我们可以采用递归的思想来实现它。
在这里插入图片描述


代码实现:

void QuickSort1(int* a,int begin, int end)//快速排序 -- hoare
{
	int right = end;
	int left = begin;
	int key = begin;
	if (begin >= end)
	{
		return;
	}
	while (left < right)
	{
		while (a[right] >= a[key] && right >left)
		{
			right--;
		}
		while (a[left] <= a[key] &&  right > left)
		{
			left++;
		}
		Swap(&a[right], &a[left]);
	}
	Swap(&a[key], &a[left]);
	key = left;
	QuickSort1(a, begin, left - 1);//左边
	QuickSort1(a, key+1, end);//右边
}

测试函数:

void Test_QuickSort1()
{
	int a[] = { 20,16,30,18,12,21,26,21 };
	QuickSort1(a, 0, sizeof(a) / sizeof(a[0]) - 1);
	PrintArray(a, sizeof(a) / sizeof(a[0]));

}

运行结果:
在这里插入图片描述


快速排序之挖坑法

挖坑思想:

  1. 首先我们和前面的hoare法一样,我们选定一个基准值,通常是数组中的第一个元素。
  2. 我们定义一个坑位(hole)放在基准值的位置的下面。
  3. 我们同理定义俩个指针leftright一个在数组的最左边一个在最右边。
  4. 不同的是,我们right指针找到比基准值小的值的时候,就直接和坑位所对应的值交换,并把right此时的位置置为hole
  5. 同理left也行动开始找值补坑,找到比基准值大的值将其放入坑位,置为新的坑。
  6. 以此往复,当leftright相遇的时候,在将基准值放入坑位。此时我们也会发现和hoare一样的排序结果,右边的值都比基准小,左边的都比其大。(如下图所示)
    请添加图片描述

代码实现:

void PartSort2(int* a,int begin ,int end)//快速排序 -- 挖坑法
{
	int right = end;
	int left = begin;
	int hole = left;

	int key = a[begin];
	if (begin >= end)
	{
		return;
	}
	while(left < right)
	{
		while(a[right] >= key && right > left)
		{
			right--;
		}
		a[hole] = a[right];
		hole = right;
		while (a[left] <= key && right > left)
		{
			left++;
		}
		a[hole] = a[left];
		hole = left;
	}
	a[hole] = key;
	QuickSort1(a, begin, hole - 1);//左边
	QuickSort1(a, hole + 1, end);//右边
}

测试函数:

void Test_PartSort2()
{
	int a[] = { 20,16,30,18,12,21,26,21 };
	PartSort2(a, 0, sizeof(a) / sizeof(a[0]) - 1);
	PrintArray(a, sizeof(a) / sizeof(a[0]));

}

运行结果:
在这里插入图片描述


快速排序之前后指针法

双指针思想

双指针法相较于前面俩种方式,是目前主流的一种写法,这里我们依然来看看单趟的走法。

  1. 这里我们依然和前面的俩种法一样,我们选定一个基准值,通常是数组中的第一个元素。
  2. 定义一个pre和一个cur指针,同理,我们让cur指针先走,如果遇到比基准值小的值我们就停下来,然后让pre指针往前走一步,我们再对其进行交换。
  3. 注意,在交换的时候我们pre指针和cur指针不能是处于同一位置。
  4. pre指针和cur指针相遇的时候,我们就让此次循环终止,在将基准值和此时的pre值进行交换即可(cur值可能已经走出边界所以不能是cur)。此时我们也会发现和hoare和挖坑法一样的排序结果,右边的值都比基准小,左边的都比其大。(如下图所示)
    请添加图片描述

代码实现

void PartSort3(int* a, int begin, int end)//双指针法   //cur遇到比key大的++cur    cur遇到比key小的值,++prev,交换pre和cur的位置的值, ++cur
{
	int pre = begin;
	int cur = pre+1;
	int key = begin;
	while (cur <= end && pre <= end)
	{
		if(a[cur] < a[key] && cur != ++pre)
		{
			Swap(&a[cur], &a[pre]);
		}
		++cur;
	}
	Swap(&a[key], &a[pre]);
	QuickSort1(a, begin, pre - 1);//左边
	QuickSort1(a, pre + 1, end);//右边
}

函数测试

void Test_PartSort3()
{
	int a[] = { 20,16,30,18,12,21,26,21 };
	PartSort3(a, 0, sizeof(a) / sizeof(a[0]) - 1);
	PrintArray(a, sizeof(a) / sizeof(a[0]));
}

运行结果:
在这里插入图片描述


快速排序之非递归排序

非递归思想

因为递归是在函数栈帧是在栈上开辟的,十分容易出现溢出的现象,为了防止这个问题,我们有一种非栈帧的方式来实现排序,就是通过非递归的方式来实现,即用栈(前面所学的数据结构中的栈)来模拟实现。

  1. 入栈一定得保证先左再右即我们先进去的是左区间,再进去的是右区间。
  2. 将每次入栈的数据进行单趟排序。
  3. 再将剩余的部分划分成 [left,key-1][key+1,right]
  4. 循环此操作直到栈中的数据全部为空即可(如果不理解可以看下图)。
    在这里插入图片描述

代码实现:

int PartSort4(int* a, int begin, int end)//双指针法   //cur遇到比key大的++cur    cur遇到比key小的值,++prev,交换pre和cur的位置的值, ++cur
{
	int pre = begin;
	int cur = pre + 1;
	int key = begin;
	while (cur <= end && pre <= end)
	{
		if (a[cur] < a[key] && cur != ++pre)
		{
			Swap(&a[cur], &a[pre]);
		}
		++cur;
	}
	Swap(&a[key], &a[pre]);
	key = pre;
	return key;
}

void QuickSortNonR(int* a, int left, int right)
{
	ST st;
	STInit(&st);
	STPush(&st, left);
	STPush(&st, right);
	while (!STEmpty(&st))
	{
		int end = STTop(&st);//右边
		STPop(&st);
		int begin = STTop(&st);//左边
		STPop(&st);
		int key = PartSort4(a, begin,end);//第一趟排序的区间
		//[left, key - 1] key [key + 1, right];
		if (key + 1 < end)//判断此时是左区间还是右区间
		{
			STPush(&st, key + 1);
			STPush(&st, end);
		}
		if (begin < key - 1)
		{
			STPush(&st, begin);
			STPush(&st, key - 1);
		}

	}
	STDestroy(&st);
}


测试函数:

void Test_QuickSortNonR()
{
	int a[] = { 20,16,30,18,12,21,26,21 };

	QuickSortNonR(a,0, sizeof(a) / sizeof(a[0]) - 1);
	PrintArray(a, sizeof(a) / sizeof(a[0]));

}

运行结果:
在这里插入图片描述


结语:今天的内容就到这里吧,谢谢各位的观看,如果有讲的不好的地方也请各位多多指出,作者每一条评论都会读的,谢谢各位。


🫵🫵🫵 这里提前祝各位新年快乐呀! 💞

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

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

相关文章

CleanMyMac X 4.14.6中文版2024年最新必备的Mac系统清理工具

CleanMyMac X 4.14.6中文版是一款专业的Mac系统清理软件&#xff0c;可一键智能扫描清理mac系统日志缓存磁盘垃圾和多余语言安装包&#xff0c;快速释放电脑内存&#xff0c;轻松管理和升级Mac上的应用。同时CleanMyMac X 破解版可以强力卸载恶意软件&#xff0c;修复系统漏洞&…

SourceTree的安装和使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、安装&#xff1a;二、使用步骤1.获取地址2.放入sourceTree 3.点击推送 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 简单讲解一…

【盘点】再见2023年,年度总结

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容事业AI大模型交互式问答图文视频生成功能型应用生成 行情危机感 爱情情绪价值会撩沟通 生理价值颜值相貌、身材体态、审美穿搭关于男性与女性间的那份本能需求生育 物质价值 &#x1f4e2;文章总结&#x1f4e5;博主目标 &…

Anolis安装Jdk保姆级教学

前言 欢迎来到本博客&#xff0c;我们将带领你完成在Anolis操作系统上安装Java Development Kit&#xff08;JDK&#xff09;的详细过程。Anolis操作系统是一款基于Linux的轻量级操作系统&#xff0c;专为容器和云原生应用而设计。在Anolis上安装JDK将为你提供一个稳定、高效的…

高校实验室安全管理视频监控系统设计:AI视频识别技术智能分析网关V4的应用

一、背景 实验室作为科研与教学的核心场所&#xff0c;其重要性不言而喻。高校实验室由于其开放性与多样性&#xff0c;安全管理尤为重要。高校实验室的安全管理&#xff0c;不仅是保障科研与教学质量的基础&#xff0c;更是校园安全的重要组成部分。一旦发生安全事故&#xf…

redis 从0到1完整学习 (八):QuickList 数据结构

文章目录 1. 引言2. redis 源码下载3. quickList 数据结构3.1 整体3.2 数据结构 4. 参考 1. 引言 前情提要&#xff1a; 《redis 从0到1完整学习 &#xff08;一&#xff09;&#xff1a;安装&初识 redis》 《redis 从0到1完整学习 &#xff08;二&#xff09;&#xff1a…

D9741 PWM控制器电路,定时闩锁、短路保护电路,输出基准电压(2.5V) 采用SOP16封装

D9741是一块脉宽调制方三用于也收路像机和笔记本电的等设备上的直流转换器。在便携式的仪器设备上。 主要特点&#xff1a;● 高精度基准电路 ● 定时闩锁、短路保护电路 ● 低电压输入时误操作保护电路 ● 输出基准电…

前端 -- 基础 常用标签 ( 图像标签及其属性详解)

目录 图像标签 &#xff1a; 插入图像 图像标签的其它属性 &#xff1a; alt 属性 title 属性 width 属性 height 属性 border 属性 注意 图像标签 &#xff1a; 在我们的网页中&#xff0c;可以看到 好多 好多 图片&#xff0c;那这些图片又是怎样 在…

万相台(万相台无界版-消费者运营/货品运营/活动运营)基础知识点总结

1.万相台是全站内推广渠道&#xff0c;相对直通车&#xff08;万相台无界版-关键词推广&#xff09;、引力魔方&#xff08;万相台无界版-精准人群推广&#xff09;可操控性弱&#xff0c;主要靠平台智能投放&#xff1b; 2.万相台经典特点&#xff1a;cpc可高可低&#xff0c…

【经典算法】有趣的算法之---蚁群算法梳理

every blog every motto: You can do more than you think. 0. 前言 蚁群算法记录 1. 简介 蚁群算法(Ant Clony Optimization, ACO)是一种群智能算法,它是由一群无智能或有轻微智能的个体(Agent)通过相互协作而表现出智能行为,从而为求解复杂问题提供了一个新的可能性…

python 异步Web框架sanic

我们继续学习Python异步编程&#xff0c;这里将介绍异步Web框架sanic&#xff0c;为什么不是tornado&#xff1f;从框架的易用性来说&#xff0c;Flask要远远比tornado简单&#xff0c;可惜flask不支持异步&#xff0c;而sanic就是类似Flask语法的异步框架。 github&#xff1…

单片机开发从小工到专家

有道无术&#xff0c;术尚可求&#xff1b;有术无道&#xff0c;止于术 背景 向单片机嵌入式开发小伙伴推荐了几本书&#xff0c;阅读量破10 1. 适用范围 2. 书籍推荐 书籍推荐 3. 大师介绍 大师介绍 4. 大师书籍编写逻辑 25年大师出版的关于&#xff1a;嵌入式单片…

别一言不合就重装系统!Windows 无法正常启动先试试这些办法

你是否遇到过在升级或安装 Windows 10 操作系统&#xff0c;Windows 无法正常启动进入桌面&#xff0c;甚至陷入无限循环。造成的原因有很多&#xff0c;比如 Windows 更新&#xff0c;安装了新的软件或者驱动程序&#xff0c;系统文件损坏等等。那遇见 Windows 启动不了怎么办…

c语言-string.h库函数初识

目录 前言一、库函数strlen()1.1 strlen()介绍1.2 模拟实现strlen() 二、库函数strcpy()2.1 strcpy()介绍2.2 模拟实现strcpy() 三、库函数strcmp()3.1 strcmp()介绍3.3 模拟实现strcmp() 总结 前言 本篇文章介绍c语言<string.h>头文件中的库函数&#xff0c;包含strlen…

Java线程池ThreadPoolExecutor源码解析

Java线程池ThreadPoolExecutor源码解析 1.ThreadPoolExecutor的构造实现 以jdk8为准&#xff0c;常说线程池有七大参数&#xff0c;通常而言&#xff0c;有四个参数是比较重要的 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit …

python零基础能学吗 知乎,python零基础可以自学吗

大家好&#xff0c;本文将围绕零基础学python这本书怎么样展开说明&#xff0c;python零基础能学吗 知乎是一个很多人都想弄明白的事情&#xff0c;想搞清楚python零基础可以自学吗需要先了解以下几个事情。 0基础学Python有多难&#xff1f;该怎么入门&#xff1f; 零基础学Py…

MR实战:实现数据去重

文章目录 一、实战概述二、提出任务三、完成任务&#xff08;一&#xff09;准备数据文件1、在虚拟机上创建文本文件2、上传文件到HDFS指定目录 &#xff08;二&#xff09;实现步骤1、Map阶段实现&#xff08;1&#xff09;创建Maven项目&#xff08;2&#xff09;添加相关依赖…

旅行旅游研学线路景点门票特产周边小程序开源版开发

旅行旅游研学线路景点门票特产周边小程序开源版开发 以下是旅行旅游研学线路景点门票特产周边小程序开源版开发的功能列表&#xff1a; 首页&#xff1a; 展示热门线路和推荐景点信息提供搜索功能&#xff0c;用户可以通过关键词搜索线路、景点、特产等显示当前位置和附近的景…

六、文件操作

文章目录 1.文件的打开与关闭1&#xff09;打开文件2&#xff09;关闭文件3&#xff09;写数据4&#xff09;读数据(read)5&#xff09;读数据&#xff08;readlines&#xff09;6&#xff09;读数据&#xff08;readline&#xff09;7&#xff09;获取当前读写的位置8&#xf…

电子学会C/C++编程等级考试2022年09月(八级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:道路 N个以 1 … N 标号的城市通过单向的道路相连:。每条道路包含两个参数:道路的长度和需要为该路付的通行费(以金币的数目来表示) Bob and Alice 过去住在城市 1.在注意到Alice在他们过去喜欢玩的纸牌游戏中作弊后,Bob和她…
最新文章