数据结构——插入排序和希尔排序

news2025/1/9 4:56:49

坚持看完,结尾有思维导图总结

这里写目录标题

  • 插入排序
    • 插入排序的步骤
      • 什么是插入排序
      • 插入排序的单趟排序
        • 单趟排序的步骤
        • 插入排序的图解
      • 完整的插入排序排序
    • 插入排序的程序
    • 插入排序的常见问题
      • 关于插入排序的时间复杂度分析
  • 希尔排序
    • 希尔排序的图解
    • 希尔排序的步骤
    • 希尔排序的程序
    • 需要强调的问题
  • 总结

插入排序

插入排序的步骤

什么是插入排序

根据官方的说法就是

把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。

简单地说,就是和扑克牌排序一样
如果你抽到一张 5,首先你要找到比他小的数
如果你找到了 3 和 4
毫无疑问你要放在 4 的后面
而不是3或者6的后面。

插入排序的单趟排序

插入排序的单趟排序要实现的目标是

如果向一个有序数组中随机插入一个数,通过插入排序,能够找到这个随机数在有序数组的位置,使得整个数组重新有序

如果向一个数组
假如数组的内容是 1 3 6 10
向其中插入数字 4

单趟排序的步骤

整个过程的步骤是
1.找到最近的比 4 小的值 a
2.通过移动a后面的值来空出 a 后面的空间
3.将 4 插入到这个值后面

插入排序的图解

在这里插入图片描述

完整的插入排序排序

单趟的插入排序的前提,是一个有序的数组
但是随机数组不会是有序的
那应该如何解决?

我们可以利用 只有一个元素的数组来解决这个问题
在这个基础上
只有一个元素的数组是有序的
随后插入一个元素后,两个元素的数组是有序的
在不断插入,最终使得整个数组有序

假如我们要排序一个数组
22 44 23 78 66 25 85
其中红圈表示就是有序数组

插入排序的图解是?
在这里插入图片描述

插入排序的程序

void InsertSort(int* a,int len)
{
	for(int i = 0;i<len-1;i++)
	{
		int end = i;
		int tmp = a[end+1];
		//单趟
		while(end>=0 && a[end]>tmp)
		{
			a[end+1] = a[end];
			end--;
		}
		a[end+1] = tmp;
	}
}

插入排序的常见问题

关于 end 的是否越界的问题
在这里插入图片描述
由于 tmp = a[end + 1]
end = i,所以 end + 1< len ,i < ken -1

end 可以为 0 ,单插入的值比第一个值还要小的时候
end – 后,end = -1越界却没有访问
之后将 tmp 插入到 end + 1的位置,end + 1= 0,此时没有越界

关于插入排序的时间复杂度分析

希尔排序的时间复杂度

如果一个数组是倒序,这个时候是最糟糕的情况
每添加一个数据,都要拿到最前面去,然后挪动数据,此处挪动数据的次数是 n ,每个数都需要挪动,时间复杂度就是 n^2
在这里插入图片描述
插入排序的空间复杂度是 O(1)
插入排序的稳定性是
因为 a[end] > tmp 的 时候都直接跳过,所以最终 a[end] <= tmp
所以,如果相同的数,本身在数组之前的值依旧在数组前面,本身在数组后的值在数组后面
所以插入排序是稳定的

希尔排序

插入排序,有一个问题,他的时间复杂度来源是,当某个数很小的时候,要挪动许多数据到前方,从而导致的时间损耗
希尔排序就是为了解决这个问题

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

而除了最后的 grip = 1 的排序,之前的排序都叫预排序

希尔排序的图解

简单地说
如果有一组数,可以按照一定的步长进行分小组
在这里插入图片描述

如果在小组内进行插入排序,就能实现数值小的数快速挪动到数组前面的效果

比如由黑色框构成的一组数(叫黑组)
当13 走到 45 前面,在实际数组中,13 就直接排头了
在这里插入图片描述

希尔排序的步骤

从图解可以提炼出步骤
1.得到步长,将数据分组
2.在组内进行插入排序

希尔排序的程序

void ShellSort(int*a,int len)
{
	int grip = len;
	// 设置步长,最后一次步长为1
	while(grip>1)
	{
		grip = grip/3 + 1;
		// 分出的组数和步长一致
		for(int group = 0;group < grip;group++)
		{
			//分组插入排序
			for(int i = group;i<len-grip;i+=grip)
			{
				int end = i;
				int tmp = a[end + grip];
				while(end >= 0 && a[end] > tmp)
				{
					a[end + grip] = a[end];
					end-=grip;
				}
				
				a[end+grip] = tmp;
				
			}
		}
	}
}

化简一下代码

void ShellSort(int*a,int len)
{
	int grip = len;
	// 设置步长,最后一次步长为1
	while(grip>1)
	{
		grip = grip/3 + 1;
		for(int i = 0;i<len-grip;i++)
		{
			int end = i;
			int tmp = a[end + grip];
			while(end >= 0 && a[end] > tmp)
			{
				a[end + grip] = a[end];
				end-=grip;
			}
			a[end+grip] = tmp;
			
		}
	}
}

需要强调的问题

希尔排序中 grip 的设计和优化的问题
首先,为了保证 grip 的大小最后为1,才能保证这个数组数顺序的
站在前人的肩膀,能够知道 grip = grip /2,和 grip = grip /3 +1 是比较合理的设计

其次,每次从首元素 k 跨过 grip 的元素 k+grip 才分成相同的小组,因此从[k , k+grip) 的元素中都是不同组的,所以 group 的数量为 grip
因为 tmp = a[end + grip ] 所以不能越界,最后 end 只能为 len - grip,再向后就越界了

关于优化前后的代码
优化前后的原理是等等效的,只是顺序不一样而已
在这里插入图片描述

左边的代码是先分组,然后再进行插入排序

右边的代码时边分组,边插入排序

最终的结果相同
在这里插入图片描述

总结

在这里插入图片描述

希望大家看完,能够有所收获
如果有错误,请指出我一定虚心改正
动动小手点赞
鼓励我输出更加优质的内容

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微服务框架 SpringCloud微服务架构 多级缓存 47 Lua 语法入门 47.3 条件控制、函数

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 多级缓存 文章目录微服务框架多级缓存47 Lua 语法入门47.3 条件控制、函数47.3.1 函数47.3.2 条件控制47 Lua 语法入门 47.3 条件控制、函数…

流水线Flow【可持续集成自动化部署】解决方案

文章目录前言一、准备项目代码1.默认的项目2.浏览器访问二、使用步骤1.进入工作台2.创建流水线3.代码源4.代码扫描5.单元测试6.代码构建7.主机部署8.部署脚本三、运行测试1.运行流水线2.测试报告3.访问项目总结前言 「流水线」&#xff0c;又名「Flow」&#xff0c;是一款企业…

Java+MySQL基于SSM的学生宿舍管理系统的设计与实现 开题 论文

随着我国教育制度的改革,各大高校一直在不断的扩招相对应的学生的数量也在不断的增加。在学生数量增加之后学校后勤人员就需要对后勤部分更加精准的进行管理,其中宿舍管理就是后勤管理中比较重要的一个组成部分。如何能够对学生的宿舍信息进行更加科学合理的管理是当前大多数高…

单张图像三维人脸重建必备入门face3d--pipeline

作者&#xff1a;小灰灰 来源&#xff1a;投稿 编辑&#xff1a;学姐 上期传送门&#x1f449;单张图像三维人脸重建必备入门face3d—3DMM 三维人脸的必备入门就要看Yao Feng写的https://github.com/YadiraF/face3d 这个代码主要介绍了3D人脸的一些功能&#xff0c;处理网格数…

Python -- 函数

目录 函数的介绍 1.函数定义和调用 2.函数的参数 2.1 定义、调用带有参数的函数 2.2 调用函数时参数的顺序 3.函数的返回值 3.1 返回值介绍&#xff1a; 3.2 带有返回值的函数 3.3 保存函数的返回值 4.文档注释 4.1 基本使用 4.2 高级使用 5.函数调用函数 6.函数高…

基于java的拼图游戏的设计与实现-计算机毕业设计

项目介绍 java版拼图游戏的功能有开始游戏&#xff0c;背景图片(可自己选择添加图片)&#xff0c;难度选择&#xff08;9格的初级&#xff0c;16格中级和以及25格的高级&#xff09;&#xff0c;成绩统计&#xff0c;分数排名等功能。游戏界面具有外观简洁美丽&#xff0c;操作…

Django学习Day4

1.静态文件 静态文件一般是指网页中的图片、js、css、音视频文件。是指不会随着用户的请求动态变更的文件信息和互联网资源。 关于静态文件的配置&#xff0c;需要在settings.py中进行指定。 &#xff08;1&#xff09;配置静态文件的访问路径。 &#xff08;2&#xff09;ST…

【NodeJs学习笔记】WebPack介绍

什么是WebPack WebPack主要用于模块打包。 它做的事情是&#xff0c;分析项目结构&#xff0c;找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言&#xff08;Scss&#xff0c;TypeScript等&#xff09;&#xff0c;并将其打包为合适的格式以供浏览器使用。 官…

如何使用 Git 操控Gitee远程库?如何进行 团队内协作 与 跨团队协作 ?这一篇就够了~

目录 前言 一、创建别名 二、推送本地库到远程库 三、拉取远程库代码到本地库 四、 克隆远程库到本地 五、团队内协作 六、跨团队协作 前言 如何通过Git操作Gitee/GitHub远程库&#xff1f;在Gitee/GitHub上如何进行 团队协作 与 跨团队协作&#xff0c;看完本篇&#x…

关于游戏介绍的HTML网页设计 HTML5期末考核大作业 HTML静态游戏网页作业 web前端开发技术 web课程设计 网页规划与设计

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

LeetCode 热题 C++ 98. 验证二叉搜索树 101. 对称二叉树

力扣98 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。示例 1&#xff1a…

记一次 .NET 某工控MES程序 崩溃分析

一&#xff1a;背景 1.讲故事 前几天有位朋友找到我&#xff0c;说他的程序出现了偶发性崩溃&#xff0c;已经抓到了dump文件&#xff0c;Windows事件日志显示的崩溃点在 clr.dll 中&#xff0c;让我帮忙看下是怎么回事&#xff0c;那到底怎么回事呢? 上 WinDbg 说话。 二&…

Linux文件权限概念

目录 前言 1、Linux 文件属性 1.1、档案类型权限 1.2、连结数 1.3、档案拥有者 1.4、档案所属群组 1.5、档案容量 1.6、档案最后被修改的时间 1.7、档名&#xff08;文件名&#xff09; 2、如何改变文件属性和权限 2.1、改变所属群组, chgrp 2.2、改变档案拥有者, c…

Codeforces Round #838 (Div. 2) E. Tree Sum(组合数学 prufer序列 枚举边算贡献)

题目 n(n<5e5)个点的树&#xff0c;边只能选-1或1&#xff0c; 若对于每个点i来说&#xff0c;i相连的所有边的乘积值为-1&#xff0c;则称这棵树是「good tree」 根据Cayley公式&#xff0c;有种树形&#xff0c; 对于每一种树形&#xff0c;每条边都有2种选择&#xff…

什么是飞书机器人?如何定时发送飞书机器人消息?

什么是飞书机器人&#xff1f; 机器人是飞书应用的一种能力类型。基于飞书的机器人能力&#xff0c;开发者能够以较低的开发成本&#xff08;只需在服务端开发&#xff09;&#xff0c;实现在飞书单聊或群组中的消息推送和简单互动&#xff0c;完成企业系统数据与飞书的互联互通…

42_CAN列表模式接收中断实验

目录 CAN结构体 CAN_InitTypeDef初始化结构体详解 发送及接收结构体: CanTxMsg及CanRxMsg详解 CAN_FilterlnitTypeDef筛选器结构体讲解 硬件连接图 实验源码 CAN结构体 从STM32的CAN外设我们了解到它的功能非常多,控制涉及的寄存器也非常丰富,而使用STM32标准库提供的各…

pandas数据分析总结

Pandas 是 Python 语言的一个扩展程序库&#xff0c;用于数据分析。其中DataFrame&#xff0c;Json&#xff0c;数据筛选的使用频次很高&#xff0c;值得重点将基本用法学习并总结。 版本信息&#xff1a;python 3.7 pandas 1.3.5 一、DataFrame DataFrame 是一个表格型的数…

【持续更新】计算机类PDF整理

计算机相关的书籍太多太多了&#xff0c;整理太多反而很乱&#xff0c;这边我根据自己的经验和理解选了一些典型的书籍&#xff0c;大部分是自己看过觉得很有用的&#xff0c;有些是听说很nice的&#xff0c;有些是经典的&#xff0c;大家可以自行下载。 持续更新中&#xff0…

Kaggle竞赛——Titanic泰坦尼克之灾(0.76315==>0.79186)

Kaggle竞赛网址&#xff1a;https://www.kaggle.com/c/titanic 上一章&#xff1a;Kaggle竞赛——Titanic泰坦尼克之灾&#xff08;保姆级基础版&#xff09; 本次Kaggle泰坦尼克之灾分析过程大致分为&#xff1a; 第1步&#xff1a;了解数据&#xff08;上一章&#xff09; …

19_SpringBoot拓展注解@SpringBootApplication和@Configuration

文章目录Spring Boot拓展注解SpringBootApplication和Configuration0x01_SpringBootApplicationSpringBootConfigurationEnableAutoConfigurationComponentScan0x02_ConfigurationFull 全模式&#xff0c;Lite 轻量级模式Spring Boot拓展注解SpringBootApplication和Configurat…