【排序】插入排序,希尔排序

前面我们讲述了冒泡排序和选择排序,我们本章讲的排序方法是插入排序,插入排序是希尔排序实现的基础函数,大家一定要好好理解插入排序的逻辑,这样才能在后面学习希尔排序的时候,更容易的去理解,我们直接开始。

目录

插入排序(以升序为例)

基本思想:

思路

代码实现:

总结

希尔排序

基本思想:

一组一组依次排序代码实现

多组同时排序

希尔排序的时间复杂度分析

总结

总结


插入排序(以升序为例)

基本思想:

直接插入排序是一种简单的插入排序法,其基本思想是:
把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。

就和我们打牌时,从小到大排牌序,当拿到一张新牌时,我们从后往前找,当最后的牌大于此时的牌,那么就让最后一张牌向后挪动一位,继续和倒数第二张比较,若倒数第二张小于此时的牌,就说明找到了位置,将此时的牌插入即可。

如上图中,此时的牌为7,那么我们从后往前找,发现10>7,那么10就往后挪动,继续向前找,发现是5,而5<7,说明找到了合适的位置将7放入5的后面即完成了插入排序。

思路

当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移

由于插入排序插入第i个元素时,需要前i-1个元素都是有序的,因此我们仍然需要从第1个元素开始排序

假设我们目前前i个是有序的,我们排序的就是第i+1个元素,我们用tmp记录a[i+1]的值,然后从后往前开始依次比较,由下标i到下标0,我们再创建循环,用变量(j=i , j >= 0 , j - -)控制循环

当 a[j] > tmp时,a[j]就向后挪动,即a[j+1] = a[ j ]  

当a[j] < tmp 时,说明已经找到了合适的位置,直接跳出循环,并将j+1的位置赋值为tmp即可

以下便是逻辑图: 

以上是找到比tmp小正常插入的情况 ,还有一种情况,当数组在tmp前内没有比tmp小的元素时,那么就会将小数放到数组首位,逻辑图如下,还是上面数组的例子。

动态逻辑图

代码实现:

void InsertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int tmp = a[i+1];
		int j = 0;
		for (j = i; j >= 0; j--)
		{
			if (a[j] > tmp)
			{
				a[j + 1] = a[j];
			}
			else
			{
				break;
			}
		}
		a[j+1] = tmp;
	}
}

小结

直接插入排序的特性总结:
1. 元素集合越接近有序,直接插入排序算法的时间效率越高
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1),它是一种稳定的排序算法
4. 稳定性:稳定

希尔排序

希尔排序法又称缩小增量法。希尔排序已经算是是排序中的大哥了,所以也比较难以理解,他是与快速排序,堆排序,归并排序在同一条赛道上的排序算法,十分的厉害。

基本思想:

希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。

可能比较难理解,希尔排序分为两个部分,首先进行预排序,再进行插入排序

预排序:跨元素进行分组排序,让数组更接近有序,这样再进行插入排序的时候,基本都是在有序的情况下,那么再进行插入排序就减少了数组挪动的次数,效率更高了。

我们假设跳的距离为gap,gap初始值为3

看一下逻辑图,我们就明白进行预排序后的效果

下面我们来单独实现代码,我们可以将代码拆分成几个小部分,依次实现,这样会让代码实现变得更加容易实现,这便是由小及大的思想

我们先来实现对单个分组排序的实现,即对红色排序的实现

代码实现的底层逻辑,依然是插入排序,只不过在进行遍历和比较的时候是一次跳跃gap个元素

大家看一下代码实现应该就能理解

部分代码实现

int gap = 3;
for (size_t i = 0; i < n - gap; i+=gap)
{
	int tmp = a[i + gap];
	int j = 0;
	for (j = i; j >= 0; j-= gap)
	{
		if (a[j] > tmp)
		{
			a[j + 1] = a[j];
		}
		else
		{
			break;
		}
	}
	a[j + gap] = tmp;
}

在完成单趟逻辑后,然后我们再建一个for循环,让gap组依次进行排序,即完成了一组一组依次排序的逻辑实现

一组一组依次排序代码实现

	int gap = 3;
	for (int k = 0; k < gap; k++)
	{
		for (size_t i = k; i < n - gap; i += gap)
		{
			int tmp = a[i + gap];
			int j = 0;
			for (j = i; j >= 0; j -= gap)
			{
				if (a[j] > tmp)
				{
					a[j + 1] = a[j];
				}
				else
				{
					break;
				}
			}
			a[j + gap] = tmp;
		}
	}

还有一种实现方法,是令多组同时进行排序,只需要修改一下逻辑代码即可

多组同时排序

int gap = 3;
for (size_t i = 0 ; i < n - gap; i++)
{

	int tmp = a[i + gap];
	int j = 0;
	for (j = i; j >= 0; j -= gap)
	{
		if (a[j] > tmp)
		{
			a[j + 1] = a[j];
		}
		else
		{
			break;
		}
	}
	a[j + gap] = tmp;
}

二者的逻辑图如图所示

希尔排序的时间复杂度分析

希尔排序的时间复杂度比较难计算,因为gap的取值方法很多,导致很难去计算

我们通过上面的逻辑分析,发现 在预排序阶段

gap越大,大的数可以更快的跳到后面,小的数可以更快的跳到前面,越不接近有序

gap越小,大的数跳到后面越慢,小的数跳到前面越慢,但越接近有序

因此控制gap的大小是增加效率的直接办法

但是如何取最适合的gap呢,根据大量数据统计,我们发现当gap = n/3时效率最高,但是我们需要+1,保证gap最后等于1

代码如下

void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)
	{
		// +1保证最后一个gap一定是1
		// gap > 1时是预排序
		// gap == 1时是插入排序
		gap = gap / 3 + 1;

		for (size_t i = 0; i < n - gap; ++i)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}
}

我们以n/3为例,以gap对时间复杂度的影响进行分析

如下

 代码实现

void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)
	{
		// +1保证最后一个gap一定是1
		// gap > 1时是预排序
		// gap == 1时是插入排序
		gap = gap / 3 + 1;

		for (size_t i = 0; i < n - gap; ++i)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}
}

小结

1. 希尔排序是对直接插入排序的优化。


2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。


3. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的希尔排序的时间复杂度都不固定,通过数据统计,希尔排序的时间复杂度大概为O(n^1.3)

4. 稳定性:不稳定

总结

以上是对插入排序和希尔排序的分析,是一种新的排序思想,其中的种种知识点也很碎很多,希望大家能够有所收获。

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

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

相关文章

3D分割新范式!浙大开源Reasoning3D:通过大视觉语言模型搞定3D部件分割

文章链接&#xff1a;https://arxiv.org/pdf/2405.19326 项目链接&#xff1a;http://tianrun-chen.github.io/Reason3D/ 今天和大家分享的是一项新任务&#xff1a;Zero-Shot 3D 推理分割&#xff0c;用于对象的部件搜索和定位。这是一种超越了以往类别特定的3D语义分割、3D…

韩语“对不起”怎么说?柯桥留学韩语培训

一、引言 在学习韩语的过程中&#xff0c;掌握如何表达歉意是非常重要的一部分。无论是日常交流还是正式场合&#xff0c;礼貌地说“对不起”能展现出你的修养和对他人的尊重。本文将详细介绍韩语中表示“对不起”的几种常用表达方式及其使用情境。 二、主体内容 1、详细解释 标…

冯喜运:6.4汇市观潮:今日黄金原油行情走势及操作策略

【黄金消息面分析】&#xff1a;在全球经济的波动中&#xff0c;美元和黄金市场的表现一直是投资者关注的焦点。最近&#xff0c;市场情绪和经济数据的波动对这两个市场产生了显著的影响。周二欧市早盘&#xff0c;现货黄金价格出现短线回调&#xff0c;金价跌破2340美元/盎司&…

【MyBatisPlus】MyBatisPlus条件查询

【MyBatisPlus】MyBatisPlus条件查询 文章目录 【MyBatisPlus】MyBatisPlus条件查询1、查询条件方式2、组合条件3、NULL值处理4、查询投影-设置【查询字段、分组】5、查询条件6、字段映射与表名映射问题导入 1、查询条件方式 MyBatisPlus将书写复杂的SQL查询条件进行了封装&…

基于ESP32-S3芯片的通用型无线模组方案,启明云端乐鑫一级代理商

随着物联网技术的飞速发展&#xff0c;智能设备正以前所未有的速度进入到我们的日常生活中&#xff0c;AIoT&#xff08;人工智能物联网&#xff09;已成为智能家居、智能设备、智能安防等领域的核心技术。 作为乐鑫一级代理商&#xff0c;基于ESP32-S3芯片&#xff0c;启明云…

武汉凯迪正大—开关柜综合试验台 通电试验车 开关柜通电测试台

产品概述 ​武汉凯迪正大KDGK-II 成套综合测试台用于高低压开关柜生产厂家对所生产的高低压开关柜进行出厂前的各项通电试验。它能提供各种交、直流电源&#xff0c;便于对开关柜的检测&#xff0c;提高工作效率。 技术参数 输入电源&#xff1a;三相四线AC380V 输出电压及电…

【JAVA架构】开发在线开具电子发票系统

【JAVA架构VUE】开发在线开具电子发票系统 对接税务厂家接口 实现销售发票开具 进项发票在线拉取 红冲发票在线开具 详细内容可以关注本人专栏等 销售发票开具 开具发票 进项发票在线拉取 红冲发票在线开具

YoloV9改进策略:Block篇|基于FasterNet的Block改进|性能和精度得到大幅度提高(独家原创)

本文使用FasterNet的Block改进YoloV9,对FasterNet的Block做了适当的修改,使其能够适配YoloV9,可以替换YoloV9的Bottleneck模块。 论文翻译:《CVPR2023年最新的网络,基于部分卷积PConv,性能远超MobileNet,MobileVit 为了设计快速神经网络,许多工作都专注于减少浮点运算…

高考杂志《高考》杂志社高考杂志社2024年第13期目录

高考论坛 新高考背景下高中生物核心素养培养的策略研究 胡世敏; 3-5《高考》投稿&#xff1a;cn7kantougao163.com 对新高考背景下职业生涯规划教育发展的思考 李昉睿; 6-8 基于新高考的高中语文现代诗歌教学探究 申艳; 9-11 “三新”改革下培养高中生英语核心…

A6110 轴相对振动监控器AMS 6500机械健康监测器

轴相对振动监控器的设计具有极高的可靠性 工厂最重要的旋转机械。此单槽显示器与一起使用 其他AMS 6500监视器构建一个完整的API 670机械保护监视器。 应用包括蒸汽、气体、压缩机和水力涡轮机械。 轴相对振动监控模块的主要功能是 通过比较准确监测轴相对振动并可靠地保护机械…

Vxe UI vue 使用 VxeUI.previewImage() 图片预览方法

Vxe UI vue 使用 VxeUI.previewImage() 图片预览方法的调用 查看 github 代码 调用全局方法 VxeUI.previewImage() 参数说明&#xff1a; urlList&#xff1a;图片列表&#xff0c;支持传字符串&#xff0c;也可以传对象数组 [{url: xx’l}] activeIndex&#xff1a;指定默…

OceanBase 4.3.0 列存引擎解读:OLAP场景的入门券

近期&#xff0c;OceanBase 发布了4.3.0版本&#xff0c;该版本成功实现了行存与列存存储的一体化&#xff0c;并同时推出了基于列存的全新向量化引擎和代价评估模型。通过强化这些能力&#xff0c;OceanBase V4.3.0 显著提高了处理宽表的效率&#xff0c;增强了在AP&#xff0…

excle中数据分析,excle导入用sql简单处理

前言&#xff1a; 办法一&#xff1a;直接用excle导入db就行&#xff0c;如果excle导如db不能用&#xff0c;就用笨办法下面这个方法去做 1、从系统中导出excle 2、db中插入相应的表和标题 3、先手动插入条件&#xff0c;把insert语句复制出来 INSERT INTO test.test (orders…

AI预测体彩排3采取888=3策略+和值012路或双胆下一一缩定乾坤测试6月4日预测第1弹

哈喽&#xff0c;各位亲爱的小伙伴&#xff0c;咱们从今天开始进行新一轮的测试验证&#xff0c;在正式开始前&#xff0c;咱们先对上一个周期的10次测试做一个总结。经过对一个周期&#xff08;10天&#xff09;的测试&#xff0c;我的AI模型对于8码定位的命中率为70%&#xf…

AI办公蓝桥杯全国总决赛获奖心得分享

从校赛到省赛&#xff0c;再到全国总决赛&#xff0c;一路走来&#xff0c;见证了自己的成长与蜕变。这篇文章将分享我在蓝桥杯大赛中的经历与心得&#xff0c;希望对正在奋斗路上的你有所启发和帮助。 1&#xff0c;从平凡到闪耀&#xff1a;自我成长的历程 最开始&#xff…

科技云报道:走出“实验室”,GenAI迎来关键拐点

科技云报道原创。 对传统产业来说&#xff0c;GenAI是一场“哥白尼式的革命”&#xff0c;它改变了传统的业务模式&#xff0c;开启了人类与AI合作的新纪元。基于AI助手和大语言模型&#xff0c;企业能够实现智能运营的目标。 如果说&#xff0c;2022年是AI大模型元年&#x…

mysql终端使用中的错误

在这个过程中&#xff0c;出现了几个问题&#xff1a; 在退出 MySQL 后&#xff0c;你尝试再次使用 mysql 命令登录&#xff0c;但系统提示找不到该命令。这可能是因为 MySQL 的执行文件路径没有加入到系统的环境变量中。你可以尝试使用绝对路径来运行 mysql 命令&#xff0c;或…

教师产假多少天

教师产假究竟有多少天&#xff1f;这个问题或许在您计划家庭时显得尤为重要。教师作为国家公职人员&#xff0c;享有法定的产假权益。 根据规定&#xff0c;女职工的产假一般为98天&#xff0c;包括产前15天和产后83天。但请注意&#xff0c;这一标准并非全国统一&#xff0c;不…

学习算法笔记(7.5)-贪心算法(股票售卖问题)

学到这里的大家应该都非常清楚贪心算法到底是怎么一回事了&#xff0c;说白了就是动态规划的一种特例&#xff0c;没有动态规划的使用范围广&#xff0c;但是效率却比动态规划效率高&#xff0c;贪心算法不考虑之前的情况&#xff0c;只考虑当前的最优选择以期达到最优的结果。…

【python】成功解决“ModuleNotFoundError: No module named ‘IPython’”错误的全面指南

成功解决“ModuleNotFoundError: No module named IPython’”错误的全面指南 一、引言 在Python编程中&#xff0c;ModuleNotFoundError是一种常见的错误类型&#xff0c;它通常表明Python解释器无法找到你试图导入的模块。特别是当你遇到“ModuleNotFoundError: No module…