【C语言/数据结构】排序(直接插入排序|希尔排序)

 🌈个人主页:秦jh__https://blog.csdn.net/qinjh_?spm=1010.2135.3001.5343
🔥 系列专栏:《数据结构》https://blog.csdn.net/qinjh_/category_12536791.html?spm=1001.2014.3001.5482

9efbcbc3d25747719da38c01b3fa9b4f.gif​​​​

目录

 插入排序

直接插入排序:

希尔排序

预排序

gap的取值

时间复杂度

​编辑 ​编辑

完整代码呈现

 


 

   前言

    💬 hello! 各位铁子们大家好哇。

             今日更新了插入排序的内容
    🎉 欢迎大家关注🔍点赞👍收藏⭐️留言📝

 

 81ede814cfe94cd2babe3f6300d32f63.png

 插入排序

直接插入排序:

下方是原理图:

 d96f573be6b19a36b1d8fb05d9fdd609.gif

 

//时间复杂度:O(N^2) 逆序
//最好的情况:O(N)  顺序有序
void InsertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;
	}
}

分析:此过程为升序。end指向第一个要比较的元素的下标,tmp为待插入元素。当tmp小于前面的元素时,把前一位元素往后移,end--,使其指向前一位(更小的)元素。当tmp不再大于前一位元素,就直接用tmp替换。需注意:for循环的结束条件。

希尔排序

 希尔排序有2步:

  1. 预排序(接近有序)(分别对每个分组进行插入排序)
  2. 直接插入排序

预排序

de7ec625ca5c46c7a7224a09ac3232e0.png

分析:我们假设每组的间隔是3,相同颜色相连的数字是同一组,红色原本是9,6,4,1,进行插入排序后就变成1,4,6,9。其他组别以此类推。这样的目的是使较大的数排后面,小的排前面,让他接近有序。最后再整体进行插入排序,这样可以提高效率。

 预排序代码实现如下:

	int gap = 3;

	//一组一组排
	//for (int j = 0; j < gap; j++)
	//{
	//	for (int i = j; i < n - gap; i += gap)
	//	{
	//		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;
	//	}
	//}

	//多组并排
	for (int 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;
	}

分析:预排序有两种写法,第二种写法比第一种少了一层循环。

我们先分析第一种:预排序是在我们前面讲的直接插入排序中修改的。内层for循环中,因为是间隔着排序,所以每次加减时都是加减gap,内层循环结束后,就完成了第一组的排序,外层for循环控制第几组排序。

第二种:少了外层的for循环,i就要从0开始,然后每次加1,这样就是混合着多组进行排序,其他步骤不变。

gap的取值

  • gap越大,大的值更快调到后面,小的值可以更快调到前面,越不接近有序。
  • gap越小,跳的越慢,但是越接近有序,如果gap==1,就是直接插入排序。
//多组并排
int gap = n;
//gap>1时是预排序,目的是让他接近有序
//gap==1是直接插入排序,目的是让他有序
while (gap>1)
{
	//gap=gap/2;
	gap = gap / 3 + 1;
	for (int 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;
	}
}

分析:在实际中,gap取值看数量情况定。当gap>1,循环进行预排序,每次/2,最后一次肯定是1。但是每次/2,进行的预排序可能还是过多,就可以/3,不过要保证最后一次是1,因为当2除以3时==0,所以就要在后面加上1。具体除以几,主要保证最后一次是1即可。

时间复杂度

7659f81ca84f44da905dc538da4a0994.png 46ecc4e90c8f40c491a6049f80a9521c.png

分析:最后一轮累计的挪动次数大约为:n 。总的平均时间复杂度是O(N^1.3),因为计算过程十分复杂,只需了解。

完整代码呈现

//平均O(N^1.3)
void ShellSort(int* a, int n)
{
	//int gap = 3;

	//一组一组排
	//for (int j = 0; j < gap; j++)
	//{
	//	for (int i = j; i < n - gap; i += gap)
	//	{
	//		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;
	//	}
	//}

	//多组并排
	int gap = n;
	//gap>1时是预排序,目的是让他接近有序
	//gap==1是直接插入排序,目的是让他有序
	while (gap>1)
	{
		//gap=gap/2;
		gap = gap / 3 + 1;
		for (int 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;
		}
	}
}

 

 

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

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

相关文章

【STM32】STM32学习笔记-Unix时间戳(41)

00. 目录 文章目录 00. 目录01. Unix时间戳02. UTC/GMT03. 时间戳转换04. C 标准库 <time.h>05. 时间相关函数示例5.1 time函数5.2 gmtime函数5.3 localtime函数5.4 mktime函数5.5 ctime函数5.6 asctime函数5.7 strftime函数 06. 预留07. 附录 01. Unix时间戳 •Unix 时…

GD32移植FreeRTOS+CLI过程记录

背景 之前我只在STM32F0上基于HAL库和CubeMX移植FreeRTOS&#xff0c;但最近发现国产化替代热潮正盛&#xff0c;许多项目都有国产化器件指标&#xff0c;而且国产单片机确实比意法的便宜&#xff0c;所以也买了块兆易创新的GD32F303开发板&#xff0c;试一试它的优劣。虽然GD…

HarmonyOS鸿蒙学习基础篇 - 通用事件

一、引言 HarmonyOS鸿蒙是华为推出的分布式操作系统&#xff0c;旨在为各种智能设备提供统一的操作系统。鸿蒙系统的一大特色是其强大的分布式能力&#xff0c;而通用事件则是实现这一能力的关键技术之一&#xff0c;本篇博客将介绍HarmonyOS鸿蒙中的通用事件。 二、 点击事件…

Vue深入学习4—指令和生命周期

1.Vue是怎么识别 v- 指令的&#xff1f; 首先将HTML结构解析成属性列表&#xff0c;存入到数组中&#xff0c;接着遍历数组中的每一个节点&#xff0c;获取到不同指令对应的方法。 // 将HTML看作真正的属性列表 var ndoeAttrs node.attributes; var self this; // 类数组对象…

使用chrome爬取URL数据的实战代码

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

JavaScript 执行上下文与作用域

执行上下文与作用域 ​ 执行上下文的概念在 JavaScript 中是颇为重要的。变量或函数的上下文决定了它们可以访问哪些数据&#xff0c;以及它们的行为。每个上下文都有一个关联的变量对象&#xff08;variable object&#xff09;&#xff0c; 而这个上下文中定义的所有变量和函…

Java项目:17 基于SpringBoot的在线拍卖系统

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 主要功能 前台登录&#xff1a; ①首页&#xff1a;轮播图、竞拍公告、拍卖商品展示 ②拍卖商品&#xff1a;分类&#xff1a;手机、数码、电器…

Vite学习指南

那本课程都适合哪些人群呢&#xff1f; 想要学习前端工程化&#xff0c;在新项目中投入使用 Vite 构建工具的朋友 Webpack 转战到 Vite 的小伙伴 前端架构师们&#xff0c;可以充实自己的工具箱 当然如果你没有项目相关开发经验&#xff0c;也可以从本课程中受益&#xff0…

【Linux】gcc中__builtin_expect的作用

本文首发于 慕雪的寒舍 引入 代码学习的时候&#xff0c;遇到了__builtin_expect这个之前从来没有遇到过的东西&#xff0c;网上搜了一下&#xff0c;发现纯C语言实现的GCD&#xff08;Grand Central Dispatch&#xff09;中就有定义过这个宏 #define _safe_cast_to_long(x) …

2017. 圆周排列

一、题目 Problem #2017 - ECNU Online Judge 二、思路 一开始以为是全排列&#xff0b;验证的问题&#xff0c;后来超时&#xff0c;然后转向组合排列思考&#xff0c;结果AC了 首先要知道&#xff1a;n个不同元素的圆排列有(n-1)!个 证明&#xff1a;将个n 元素中的某个元素…

语图奇缘:林浩然与杨凌芸的哲学漫画大冒险

语图奇缘&#xff1a;林浩然与杨凌芸的哲学漫画大冒险 Language Odyssey: The Philosophical Comic Adventure of Lin Haoran and Yang Lingyun 在一个充满逻辑谜题和言语陷阱的城市——逻言市&#xff0c;住着两位热衷于探索语言奥秘的年轻人&#xff0c;林浩然和杨凌芸。林浩…

docker之部署青龙面板

青龙面板是一个用于管理和监控 Linux 服务器的工具&#xff0c;具有定时运行脚本任务的功能。在实际情况下也可以用于一些定期自动签到等任务脚本的运行。 本次记录下简单的安装与使用&#xff0c;请提前安装好docker&#xff0c;参考之前的文章。 一、安装部署 1、拉取镜像 # …

黑马点评Redis项目实战(1)基于Session实现短信登录

一、导入黑马点评项目 1.后端部署 下载好资料之后&#xff0c;先在数据库中制作所需的表&#xff0c;如下&#xff1a; 接着在工程中按照自己的数据库设置相应的username和root&#xff0c;如下&#xff1a; 启动项目之后&#xff0c;输入网站&#xff1a;localhost:8081/sho…

【原神游戏开发日志3】登录和注册有何区别?

版权声明&#xff1a; ● 本文为“优梦创客”原创文章&#xff0c;您可以自由转载&#xff0c;但必须加入完整的版权声明 ● 文章内容不得删减、修改、演绎 ● 本文视频版本&#xff1a;见文末 ● 相关学习资源&#xff1a;见文末 前言 ● 这是我们原神游戏开发日记的第三期 ●…

【Java面试】Mysql

目录 sql的执行顺序索引的优点和缺点怎么避免索引失效(也属于sql优化的一种)一条sql查询非常慢&#xff0c;我们怎么去排查和优化&#xff1f;存储引擎 MylSAM和InnoDB、Memory的区别事务的四大特性(ACID)脏读、不可重复读、幻读事务的隔离级别&#xff1f;怎么优化数据库SQL优…

fastapi学习

fastapi框架 fastapi&#xff0c;一个用于构建 API 的现代、快速&#xff08;高性能&#xff09;的web框架。 fastapi是建立在Starlette和Pydantic基础上的&#xff0c;Pydantic是一个基于Python类型提示来定义数据验证、序列化和文档的库。Starlette是一种轻量级的ASGI框架/工…

春运倒计时,AR 引领铁路运输安全新风向

根据中国交通新闻网发布最新消息&#xff0c;今年春运全国跨区域人员流动量预计达 90 亿人次。 随着春运期间旅客数量不断创下新高&#xff0c;铁路运输面临着空前的挑战与压力。 图源&#xff1a;pixabay 聚焦铁路运输效率与旅客安全保障问题&#xff0c;本期行业趋势将探讨 …

在 Vue 项目中,可以通过设置不同的环境变量来区分不同的环境,例如本地开发环境、测试环境和生产环境。以下是设置环境变量的步骤:

1、在src下新建三个文件夹 &#xff08;.env.local、.env.test 和 .env.prod&#xff09; 2、配置信息 .env.local VUE_APP_ENVlocal VUE_APP_API_URLhttp://localhost:8080.env.test VUE_APP_ENVtest VUE_APP_API_URLhttp://124.220.110.203:9090/ .env.prod VUE_APP_…

看门狗定时器

1. 看门狗 看门狗: 用于设备在 程序异常(死机) 时 可以自动重启设备 实现原理: 通过定时器 进行定时 , 在定时器时间结束前 进行 "喂狗" 重置定时器时间 若时间到,还没有"喂狗",系统重启 本质就是一个定时器, 如何定时? 定时器 本质是对 晶振时钟进行 计…

上位机图像处理和嵌入式模块部署(c/c++ opencv)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 opencv可以运行在多个平台上面&#xff0c;当然windows平台也不意外。目前来说&#xff0c;opencv使用已经非常方便了&#xff0c;如果不想自己编译…