11 插入排序和希尔排序

1. 插入排序

基本思想
直接插入排序是一种简单的插入排序法,基本思想:

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

在玩扑克牌时,就用了插入排序的思想

在这里插入图片描述

过程
在这里插入图片描述

类似扑克牌,手里有3,7,8,9,,四张牌,这时,如果摸到4,怎么排它的位置。先和9比,小于9,再和前面的8比,再和7比,再和3比,这时大于3,就找到了它该插入的位置,将4放在3的后面,其他的往后挪一个

在这里插入图片描述

从7开始排,第一个数肯定是有序的。
然后是4,4小于7,所以7应该在4的前面,将7往后挪一位,4放在7的位置
5比7小,7往后挪,5比4大,所以5的位置就是4的后面

这样不断比较,直到最后一个数排完

void Sort(int ary[], int len)
{
	//第一个是有序的,从第二个开始
	for (int i = 1; i < len; i++)
	{
		//[0,end]的区间是有序的,end是待排序数的前一个下标
		int end = i - 1;
		int temp = ary[i];
		while (end >= 0)
		{
			if (ary[end] > temp)
			{
				ary[end + 1] = ary[end];
				end--;
			}
			else
			{
				break;
			}
		}
		//此时,end是前一个位置
		ary[end + 1] = temp;
	}
	
}

特性总结:
1.元素集合越接近有序,直接插入排序算法的时间效率越高
2.时间复杂度:最坏O(N2),逆序的时候最坏,最好是O(N),正序的时候
3.空间复杂度: O(1)
4.稳定性:稳定

插入和冒泡
两者在最好和最坏的情况下时间复杂度相同,但对于大部分有序,局部无序的情况下,插入的适应性更强
在这里插入图片描述

上面的数据只有最后面的9和8无序,对于冒泡排序来说,需要第一轮比过去,交换8和9,第二轮到9的位置后发现有序,排序完毕。插入排序来说,检查到8的时候,一交换,排序完毕。这时,插入排序的效率高。冒泡排序更容易理解,比较容易上手

2. 希尔排序

基本思想
希尔排序又称缩小增量法,基本思想是:先选定一个整数,把待排序文件中所有记录分成几个组,对每一组内的记录进行排序。然后缩小分组间隔。重复上述过程,当增量缩小到1时,所有记录排为一组,排好序

插入排序对大部分有序的数据效率很高,但对于倒序的效率很低。可以根据这个特性优化。先对数据用一种效率高的方法进行预排序,使数据接近有序。最后再进行一次插入排序,就可以排序成功

过程
在这里插入图片描述
首先将整个数组按间隔gap分组,分为gap组,这里以间隔3分组

在这里插入图片描述

上面的从9开始每间隔3分为归为一组,9,6,3,1分到了一组

然后从8开始分组,直到将所有数据分组完
在这里插入图片描述
以颜色区分分为了3组,首先写一个类似的插入排序对红色组排序

void ShellSort(int ary[], int len)
{
//间隔3
	int gap = 3;
//0,从end+gap开始往前对比,到组内最后一个数排完,每次加间距
		for (int i = 0; i < len - gap; i += gap)
		{
			int end = i;
			int temp = ary[gap + end];
//将gap+end下标,也就是组内下一个数和前面的所有对比交换
			while (end >= 0)
			{
				if (ary[end] > temp)
				{
					ary[gap + end] = ary[end];
					end = end - gap;
				}
				else
				{
					break;
				}
			}

			ary[end + gap] = temp;
		}	
}

在这里插入图片描述
将红色组排好了序,接着将其他两组也排好序,意味着需要循环组数的次数,控制变量i

	int gap = 3;
	//循环gap组
	for (int j = 0; j < gap; j++)
	{
		//从end+gap开始往前对比,找组内下一个数,每次加间距
		for (int i = j; i < len - gap; i += gap)
		{
			int end = i;
			int temp = ary[gap + end];
			//将gap+end下标,也就是组内下一个数和前面的所有对比交换
			while (end >= 0)
			{
				if (ary[end] > temp)
				{
					ary[gap + end] = ary[end];
					end = end - gap;
				}
				else
				{
					break;
				}
			}

			ary[end + gap] = temp;
		}
	}
	
}

在这里插入图片描述

上面的数字仍是无序的,但经过预排序已经大部分有序

上面的三层循环可以减到2层循环,最外层的循环可以去掉。实际上外面两层循环本质上是把所有数据遍历了一遍,所以可以只用一层,多组并排,i每次递增1

void ShellSort(int ary[], int len)
{
	int gap = 3;

	//从end+gap开始往前对比,找组内下一个数,每次加间距
	for (int i = 0; i < len - gap; i++)
	{
		int end = i;
		int temp = ary[gap + end];
		//将gap+end下标,也就是组内下一个数和前面的所有对比交换
		while (end >= 0)
		{
			if (ary[end] > temp)
			{
				ary[gap + end] = ary[end];
				end = end - gap;
			}
			else
			{
				break;
			}
		}

		ary[end + gap] = temp;
	}
}

怎么让大部分有序的数据变为有序,只需要控制gap的变化,当gap=1时,就是插入排序。gap应该根据数据量变化,数据量大的时候,gap的跳跃变大,gap越大,越接近无序,但可以更快的将更大更小的数放在两端的位置

为了使排的数据最终变有序,gap的值最后必须可以变为1,官方给出的是gap每次/3+ 1,当gap为2时,就变为0,所以/3后再加1,这样无论多少数据,最终都会分为一组

void ShellSort(int ary[], int len)
{
	int gap = len;
	//gap>1预排序
	//gap=1插入排序
	while (gap > 1)
	{
		//+1保证最后一次是1
		//gap = gap/2
		gap = gap / 3 + 1;
		//从end+gap开始往前对比,找组内下一个数,每次加间距
		for (int i = 0; i < len - gap; i++)
		{
			int end = i;
			int temp = ary[gap + end];
			//将gap+end下标,也就是组内下一个数和前面的所有对比交换
			while (end >= 0)
			{
				if (ary[end] > temp)
				{
					ary[gap + end] = ary[end];
					end = end - gap;
				}
				else
				{
					break;
				}
			}

			ary[end + gap] = temp;
		}
	}
	
}

时间复杂度
在这里插入图片描述
gap/3这一层时间复杂度log3N,因为每次都除以3。而对于里面的两个循环,时间复杂度计算比较麻烦,大致可认为是O(N)。因为gap每次都是变化的,且前面的排序对后面排序的增益效果无法估算
在这里插入图片描述
上面只能以最坏的情况计算,但gap越小,情况应该是越好的

特性
1.希尔排序是对直接插入排序的优化
2.当gap>1时是预排序,目的是让数组更接近有序。gap==1时,数组已经接近有序了,就会很快
3.时间复杂度: O(N1.3)
在这里插入图片描述

在这里插入图片描述

3.稳定性: 不稳定

3. 插入排序和希尔排序比较

随机生成10万个数字,计算两个排序所消耗的时间,大致差了100倍
在这里插入图片描述

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

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

相关文章

虚拟存储器

第五章&#xff1a;虚拟存储器 常规存储管理方式的特征 一次性 驻留性 局部性原理 程序在执行时将呈现出局部性特征&#xff0c;即在一较短的时间内&#xff0c;程序的执行仅局限于某个部分&#xff0c;相应地&#xff0c;它所访问的存储空间也局限于某个区域 时间局限性 …

创建一个Vue项目(含npm install卡住不动的解决)

目录 1 安装Node.js 2 使用命令提示符窗口创建Vue 2.1 打开命令提示符窗口 2.2 初始Vue项目 2.2.1 npm init vuelatest 2.2.2 npm install 3 运行Vue项目 3.1 命令提示符窗口 3.2 VSCode运行项目 1 安装Node.js 可以看我的这篇文章《Node.js的安装》 2 使用命令提示…

【定位·HTML】

定位布局可以分为以下四种&#xff1a; 静态定位&#xff08;inherit&#xff09; 相对定位&#xff08;relative&#xff09; 绝对定位&#xff08;absolute&#xff09; 固定定位&#xff08;fixed&#xff09; 一般的标签元素不加任何定位属性时&#xff0c;默认都属于静态…

STM32标准库——(9)TIM编码器接口

1.编码器接口简介 Encoder Interface 编码器接口编码器接口可接收增量&#xff08;正交&#xff09;编码器的信号&#xff0c;根据编码器旋转产生的正交信号脉冲&#xff0c;自动控制CNT自增或自减&#xff0c;从而指示编码器的位置、旋转方向和旋转速度每个高级定时器和通用定…

linux ln命令-linux软链接、硬链接-linux软、硬链接的区别(二):软链接

0、序 上一篇&#xff1a;linux ln命令-linux软链接、硬链接-linux软、硬链接的区别(一)&#xff1a;硬链接 描述了硬链接相关内容&#xff0c;本篇主要描述软链接。 1、软链接 符号链接也称软链接&#xff0c;是将一个路径名链接到一个文件。这些文件是一种特别类型的文件。…

已解决!AttributeError: ‘Sequential‘ object has no attribute ‘session‘ 问题

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通Golang》…

【Android新版本兼容】onBackPressed()方法被弃用的解决方案

提示&#xff1a;此文章仅作为本人记录日常学习使用&#xff0c;若有存在错误或者不严谨得地方欢迎指正。 文章目录 一、使用 AndroidX API 实现预测性返回手势1.1 添加依赖1.2 启用返回手势1.3 注册OnBackPressedCallback()方法来处理返回手势 一、使用 AndroidX API 实现预测…

React | Center 组件

在 Flutter 中有 Center 组件&#xff0c;效果就是让子组件整体居中&#xff0c;挺好用。 React 中虽然没有对应的组件&#xff0c;但是可以简单封装一个&#xff1a; index.less .container {display: flex;justify-content: center;align-items: center;align-content: ce…

京东微前端框架MicroApp简介

一、MicroApp 1.1 MicroApp简介 MicroApp是由京东前端团队推出的一款微前端框架,它从组件化的思维,基于类WebComponent进行微前端的渲染,旨在降低上手难度、提升工作效率。MicroApp无关技术栈,也不和业务绑定,可以用于任何前端框架。 官网链接:https://micro-zoe.gith…

Neo4j安装部署(windows、docker)

文章目录 Neo4j安装部署前言windows系统安装解压压缩包并进入bin目录查看neo4j的相关命令访问7474端口 Docker安装Neo desktop安装 Neo4j安装部署 前言 这篇blog所涉及的资源都可以在[neo4j相关资源]进行下载。 windows系统安装 解压压缩包并进入bin目录 查看neo4j的相关命…

正则表达式与文本处理工具

目录 引言 一、正则表达式基础 &#xff08;一&#xff09;字符匹配 1.基本字符 2.特殊字符 3.量词 4.边界匹配 &#xff08;二&#xff09;进阶用法 1.组与引用 2.选择 二、命令之-----grep &#xff08;一&#xff09;基础用法 &#xff08;二&#xff09;高级用…

FL Studio 21.2.2官方中文版重磅发布2024最新FL21下载安装图文使用教程

FL Studio 21.2.2中文版惯称水果编曲, 是一个完整的电音软件音乐制作环境或数字音频工作站。是现在流行的数字音频工作站之一,包括撰写,整理,记录,编辑,电音,混音和掌握专业品质的音乐。 FL Studio 21.2.2编曲软件即“Fruity Loops Studio”&#xff0c;简称FL&#xff0c;也就…

【C++初级篇】C++入门

目录 1. C关键字(C98) 2. 命名空间 2.1 命名空间定义 2.2 命名空间使用 3. C输入&输出 4. 缺省参数 4.1 缺省参数概念 4.2 缺省参数分类 5. 函数重载 5.1函数重载概念 5.2 C支持函数重载的原理--名字修饰(name Mangling) 6. 引用 6.1 引用概念 6.2 引用特性 6.3 常引用 6.4…

时间复杂度为 O(n) 的排序算法

大家好&#xff0c;我是 方圆。本文介绍线性排序&#xff0c;即时间复杂度为 O(n) 的排序算法&#xff0c;包括桶排序&#xff0c;计数排序和基数排序&#xff0c;它们都不是基于比较的排序算法&#xff0c;大家重点关注一下这些算法的适用场景。 桶排序 桶排序是分治策略的一…

内网信息收集-Windows篇

目录 内网信息收集 机器角色分析 本机的信息收集 密码信息 如何查找内网的网段 进程、端口、补丁、共享文件夹 总结 域环境信息收集 MSF信息收集 内网信息收集 机器角色分析 1、判断当前主机是什么服务器&#xff1f; web服务器、开发测试服务器、公共服务器、文件服…

[word] 怎么将word文档中的文字转换成一个4行5列的表格 #职场发展#笔记#经验分享

怎么将word文档中的文字转换成一个4行5列的表格 怎么将word文档中的文字转换成一个4行5列的表格&#xff1f; 将文档中的四行文字转换成一个4行5列的表格的具体步骤如下&#xff1a; 1、首先打开需要编辑的Word文档&#xff0c;进入到编辑页面中。 2、然后选中需要编辑的文字…

​Nacos搭建注册中心与配置中心

目录 一、Nacos的安装和部署 1. 下载Nacos 2. 解压安装包到本地 3. 配置数据库&#xff08;可选&#xff09; 4. 启动Nacos服务 5. 登陆控制台 二、springboot整合Nacos 1. 添加依赖 2. 配置注册中心、配置中心 3. 演示 Nacos是一个平台产品&#xff0c;主要提供注册…

《数据安全法》解读篇

《中华人民共和国数据安全法》 颁布时间&#xff1a;2021年6月10日实施时间&#xff1a;2021年9月1日《中华人民共和国数据安全法》整体架构图 数据安全的定义&#xff1a;是指通过采取必要措施&#xff0c;确保数据处于有效保护和合法利用的状态&#xff0c;以及具备保障持续…

使用ESP32-S3对MQ-135空气质量传感器的使用记录(Arduino版)

一、硬件上&#xff1a; 1、使用esp32开发板的04引脚与AO连接&#xff0c;检测AO引脚的电平 二、软件上&#xff1a; 1、使用Arduino快速完成开发 2、源码&#xff1a; // Potentiometer is connected to GPIO 04 (Analog ADC1_CH3) const int adcPin 4;// variable for s…

从零学习Linux操作系统 第二十五部分 文本处理工具

一、grep命令的基本使用方法及常用参数介绍 grep [全称&#xff1a;Globally search a Regular Expression and Print 全局搜索正则表达式并打印 ] grep 命令格式 grep 匹配条件 处理文件 grep root passwd过滤root关键字grep -i root passwd后略大小写grep -E “<root”…