c语言快速排序(霍尔法、挖坑法、双指针法)图文详解

快速排序介绍:

  快速排序是一种非常常用的排序方法,它在1962由C. A. R. Hoare(霍尔)提的一种二叉树结构的交换排序方法,故因此它又被称为霍尔划分,它基于分治的思想,所以整体思路是递归进行的。

整体思路:

1.先选取一个key,关于key值的选取,一般是选数组第一个元素,数组中间元素,数组最后一个元素,这三个元素的中间值,并将这个元素与数组第一个元素进行交换。

2.将key放入整个区间中正确的位置,即为key左边的元素都比key小,右边的元素都比key要大,此时的key就是它排好序的位置,注意key左边的元素都比它小,但不一定有序,右边也是一样,然后根据递归的思想,再对key左边的区间进行上面一样的操作和key右边的区间进行上面一样的的操作,当区间不存在或者区间只有一个元素时返回。

如何将key放入正确的位置:

  将key放入正确的位置正是每趟递归需要做的,那么具体该如何实现呢?

  实现过程目前有三种方法,每种方法虽然写法不同,但总体思路一样,所以效率是相同的,只要完全理解快速排序,写哪种都一样。

1.霍尔版本(传统方法)

第一步:定义一个right从数组最后一个元素开始即数组的右边开始向左边遍历,如果找到比key小的值就停下来。

第二步:定义一个left从数组第一个元素开始即数组的左边开始向右遍历,如果找到比key大的值就停下来。

第三步:left和right都停下来之后,交换left和right的值,这一步的目的就是将比key小的值往左放,将比key大的值。

第四步:当left和right相遇后,将第一个元素(即为key的值)与它们相遇位置的值交换。

第五步:让他们相遇位置的左区间和右区间同样执行上述四步(即为递归)。

动态思路图:

  

代码实现:

void Swap(int* a, int* b)
{
	int tmp = 0;
	tmp = *a;
	*a = *b;
	*b = tmp;
}

int GetMidi(int* a, int begin, int end)
{
	int midi = (begin + end) / 2;
	if (a[begin] > a[midi])
	{
		if (a[midi] > a[end])
		{
			return midi;
		}
		else if (a[end] > a[begin])
		{
			return begin;
		}
		else
		{
			return end;
		}
	}
	else
	{
		if (a[begin] > a[end])
		{
			return begin;
		}
		else if (a[end] > a[midi])
		{
			return midi;
		}
		else
		{
			return end;
		}
	}
}

void QuickSortHoare(int* a, int begin, int end)
{
	int left = begin;
	int right = end;
	if (left >= right)
	{
		return;
	}
	int midi = GetMidi(a, begin, end);
	Swap(&a[begin], &a[midi]);
	int keyi = begin;
	while (left < right)
	{
		while (left < right && a[right] >= a[keyi])
		{
			right--;
		}
		while (left < right && a[left] < a[keyi])
		{
			left++;
		}
		Swap(&a[left], &a[right]);
	}
	Swap(&a[left], &a[keyi]);
	keyi = left;
	QuickSortHoare(a, begin, keyi - 1);
	QuickSortHoare(a, keyi + 1, end);
}

2.挖坑法:

第一步:将key的位置(即为第一个元素的位置)作为第一个坑位,将key的值一直保存在变量key中。

第二步:定义一个right从数组最后一个元素开始即为数组右边开始向左遍历,如果找到比key小的值,right停下来,将right下标访问的元素赋值到上一个坑位,并将right作为新的坑位。

第三步:定义一个left从数组第一个元素开始即为数组左边开始向右遍历,如果找到比key大的值,left停下来,将left下标访问的元素赋值到上一个坑位,并将left作为新的坑位。

第四步:当right和left相遇时,此时它们访问的元素绝对是坑位,只需将key里保存的key值放入坑位即可。

第五步:让他们相遇位置的左区间和右区间同样执行上述四步(即为递归)。

思路图:

代码实现:

void Swap(int* a, int* b)
{
	int tmp = 0;
	tmp = *a;
	*a = *b;
	*b = tmp;
}

int GetMidi(int* a, int begin, int end)
{
	int midi = (begin + end) / 2;
	if (a[begin] > a[midi])
	{
		if (a[midi] > a[end])
		{
			return midi;
		}
		else if (a[end] > a[begin])
		{
			return begin;
		}
		else
		{
			return end;
		}
	}
	else
	{
		if (a[begin] > a[end])
		{
			return begin;
		}
		else if (a[end] > a[midi])
		{
			return midi;
		}
		else
		{
			return end;
		}
	}
}
void QuickSortHole(int* a, int begin, int end)
{
	int left = begin;
	int right = end;
	if (begin >= end)
	{
		return;
	}
	int midi = GetMidi(a, begin, end);
	Swap(&a[begin], &a[midi]);
	int key = a[begin];
	int hole = begin;
	while (left < right)
	{
		while (left < right && a[right] >= key)
		{
			right--;
		}
		a[hole] = a[right];
		hole = right;
		while (left < right && a[left] <= key)
		{
			left++;
		}
		a[hole] = a[left];
		hole = left;
	}
	a[hole] = key;
	int keyi = hole;
	QuickSortHole(a, begin, keyi - 1);
	QuickSortHole(a, keyi + 1, end);
}

3.双指针法(新手推荐)

第一步:定义两根指针cur和prev,初始位置如下图所示:

第二步:cur开始往后走,如果遇到比key小的值,则++prev,然后交换prev和cur指向的元素,再++cur,如果遇到比key大的值,则只++cur。

第三步:当cur访问过最后一个元素后,将key的元素与prve访问的元素交换位置。cur访问完整个数组后的各元素位置如下图所示:

第四步:让prev的左区间和右区间同样执行上述三步(即为递归)。

代码实现:

void Swap(int* a, int* b)
{
	int tmp = 0;
	tmp = *a;
	*a = *b;
	*b = tmp;
}

int GetMidi(int* a, int begin, int end)
{
	int midi = (begin + end) / 2;
	if (a[begin] > a[midi])
	{
		if (a[midi] > a[end])
		{
			return midi;
		}
		else if (a[end] > a[begin])
		{
			return begin;
		}
		else
		{
			return end;
		}
	}
	else
	{
		if (a[begin] > a[end])
		{
			return begin;
		}
		else if (a[end] > a[midi])
		{
			return midi;
		}
		else
		{
			return end;
		}
	}
}

void QuickSortD(int* a, int begin, int end)
{
	if (begin >= end)
	{
		return;
	}
	int midi = GetMidi(a, begin, end);
	Swap(&a[begin], &a[midi]);
	int keyi = begin;
	int prev = begin;
	int cur = begin + 1;
	while (cur <= end)
	{
		if (a[cur] < a[keyi] && ++prev != cur)
		{
			Swap(&a[cur], &a[prev]);
		}
		cur++;
	}
	Swap(&a[keyi], &a[prev]);
	keyi = prev;
	QuickSortD(a, begin, keyi - 1);
	QuickSortD(a, keyi + 1, end);
}

下期预告:非递归

  这期讲的三种快速排序方法均是采用递归的方法来实现的,那么如何使用非递归来实现快速排序呢?下期我将发布快速排序的非递归法。

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

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

相关文章

基于Java+Swing+mysql学生选课成绩信息管理系统

基于JavaSwingmysql学生选课成绩信息管理系统 一、系统介绍二、功能展示三、项目相关3.1 乱码问题3.2 如何将GBK编码系统修改为UTF-8编码的系统&#xff1f; 四、其它1.其他系统实现 五、源码下载 一、系统介绍 学生教师信息管理、年级班级信息管理、课程信息管理、选课、成绩…

vue3+vite4中使用svg,使用iconfont-svg图标

记录一下vue3中如何使用svg图标&#xff0c;vue2中大家常用iconfont字体图标&#xff0c;现在vue3大家都又推荐svg的方式使用图表&#xff0c;包括elementplus组件库也变成使用svg方式引用图标。 1、创建svg组件 components/IconSvg.vue <template><svg class"…

Imagen 2 发布、Gemini Pro 免费体验、代码平台 Duet AI 上线,谷歌大爆发

在上周发布 Gemini 后&#xff0c;本周谷歌又有了新动作。 12 月 13 日&#xff0c;谷歌在其云平台上推出了一系列 AI 模型以供用户体验并实际应用&#xff1a;向开发者和企业开放 Gemini Pro、面向开发者和安全运营的 Duet AI、图像生成 Imagen 2 以及用于医疗保健场景的 Med…

python安装教程(2020最新),python安装详细教程

这篇文章主要介绍了python安装教程(2020最新)&#xff0c;具有一定借鉴价值&#xff0c;需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获&#xff0c;下面让小编带着大家一起了解一下。 1.从python官网下载python的安装包&#xff0c;我用的之前3.7.9的安装包 2.双击打…

成绩分级 C语言xdoj53

问题描述 给出一个百分制的成绩&#xff0c;要求输出成绩等级A,B,C,D,E。90分以上为A&#xff0c;80~89分为B,70~79分为C,60~69分为D&#xff0c;60分以下为E。 输入说明 输入一个正整数m&#xff08;0<m<100&#xff09; 输出说明 输出一个字符 输入样例 …

中兴 H108NS 路由器 tools_admin.asp权限绕过漏洞复现

0x01 产品简介 中兴H108NS路由器是一款集WiFi管理、路由分配、动态获取上网连接等功能于一体的路由器产品。 0x02 漏洞概述 中兴H108NS路由器tools_admin.asp接口处存在身份认证绕过漏洞,攻击者可利用该漏洞绕过身份认证允许访问路由器的管理面板修改管理员密码,获取用户的…

解决msvcr90.dll丢失的方法,3分钟搞定dll丢失问题

众所周知&#xff0c;在电脑操作时&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcr90.dll丢失”。这个问题可能会导致某些程序无法正常运行。本文就将提供五种有效方案来化解这一难题&#xff0c;帮助各位网友迅速恢复程序的运行功能。 一、msvcr90.d…

5.鸿蒙hap可以直接点击包安装吗?

5.鸿蒙hap可以直接点击包安装吗&#xff1f; hap与apk不同&#xff0c;获取的hap不能直接安装 安装方法1&#xff1a; DevEco studio打开项目源文件&#xff0c;打开手机USB调试&#xff0c;DevEco识别到手机后&#xff0c;点击播放按钮安装到手机 https://txwtech.blog.cs…

IIS + Axios 跨域设置

1、服务器端设置IIS &#xff08;web.config) 即可&#xff0c;不需要对django settings.py做配置&#xff08;python manage.py runserver 才需要settings.py配置跨域&#xff0c;IIS在iis上配&#xff09; 网站根目录的web.config中加上这段&#xff1a; <httpProtocol&…

kafka学习笔记--Topic 数据的存储机制

本文内容来自尚硅谷B站公开教学视频&#xff0c;仅做个人总结、学习、复习使用&#xff0c;任何对此文章的引用&#xff0c;应当说明源出处为尚硅谷&#xff0c;不得用于商业用途。 如有侵权、联系速删 视频教程链接&#xff1a;【尚硅谷】Kafka3.x教程&#xff08;从入门到调优…

计算机操作系统-第十六天

目录 线程的实现方式 用户级线程 内核级线程 多线程模型 一对一模型 多对多模型 多对多模型 本节思维导图 线程的实现方式 用户级线程 历史背景&#xff1a;早期操作系统只支持进程&#xff0c;不支持线程&#xff0c;当时的线程是由线程库实现的 本质&#xff1a;从…

【TI毫米波雷达入门-11】毫米波速度相关计算

知识回顾 傅里叶变换 信号用复数表示&#xff0c;A :振幅&#xff0c; Q &#xff1a;相位 中频 信号 中频信号的相位 中频信号的表达公式 频率和相位的表达方式 使用两个Chirp 实现单个目标的测量 两个连续的chirp &#xff0c;检测目标的相位差&#xff0c;通过速度和时间的关…

性能监控体系:InfluxDB Grafana Prometheus

InfluxDB 简介 什么是 InfluxDB &#xff1f; InfluxDB 是一个由 InfluxData 开发的&#xff0c;开源的时序型数据库。它由 Go 语言写成&#xff0c;着力于高性能地查询与存储时序型数据。 InfluxDB 被广泛应用于存储系统的监控数据、IoT 行业的实时数据等场景。 可配合 Te…

Redisson分布式锁原理分析

1.Redisson实现分布式锁 在分布式系统中&#xff0c;涉及到多个实例对同一资源加锁的情况&#xff0c;传统的synchronized、ReentrantLock等单进程加锁的API就不再适用&#xff0c;此时就需要使用分布式锁来保证多服务之间加锁的安全性。 常见的分布式锁的实现方式有&#xff…

MySQL下载、安装、配置详细教程

目录 1 下载 2 安装 2.1执行安装命令&#xff1a; 2.2 编写配置文件 2.3查看默认mysql的密码&#xff1a; 2.4启动mysql服务 2.5 登录mysql&#xff0c;修改密码 3 系统环境变量配置 3.1 配置 3.2 测试 1 下载 官方网址&#xff1a; https://www.mysql.com/跳转到如…

【MATLAB】基于SVMD分解的信号去噪算法(基础版)

代码的使用说明 【MATLAB】基于SVMD去噪的信号去噪算法&#xff08;基础版&#xff09; 代码的原理 1.SVMD原理 连续变分模式分解&#xff08;Successive Variational Mode Decomposition&#xff0c;SVMD&#xff09;是一种用于将混合信号根据其频率特性分离成各个独立分量的…

CSS第二天导读

1&#xff0c;Emmet语法 Emmet语法的前身是Zen coding&#xff0c;它使用缩写&#xff0c;来提高html / css 的编写速度&#xff0c;Vscode内部已经集成该语法 1.1&#xff0c;快速生成HTML结构语法 1.想要快速生成多个相同标签&#xff0c;加上*就可以了&#xff0c;比如 d…

Unity 关于Rigidbody刚体组件的理解

一、基本了解 刚体Rigidbody因具体物理相关的属性&#xff0c;使得实际应用中更有真实感。应用也多&#xff1a; Rigidbody它可以受到重力、碰撞或者力的作用&#xff0c;所以我们可以用它模拟物体的真实物理行为&#xff0c;如受到重力的作用、与其他刚体对象进行碰撞&#…

计算机毕业设计 SpringBoot的医院门诊在线挂号系统 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

pandas空格及网页空格符NBSP替换处理

df3[动作一课程内容]df3[动作一课程内容].str.replace( ,) df3[动作一课程内容]df3[动作一课程内容].str.replace( ,) 截图中代码为python展示代码&#xff0c;由于网页空格符和常规空格符看起来大致相同&#xff0c;但却不能用常规空格替换解决