【数据结构】插入排序

news2024/11/20 12:35:56

插入排序

  • 1. 排序
  • 2.插入排序
    • 2.1直接插入排序
    • 2.2折半插入法
    • 2.3希尔排序


1. 排序

  1. 排序的概念
    排序就是将一组杂乱无章的数据按一定规律(顺序或者逆序)排列起来。

  2. 排序的目的
    方便查找元素。

  3. 内部排序和外部排序
    若待排序记录都在内存中,称为内部排序;若待排序记录一部分在内存,一部分在外存,则称为外部排序。

  4. 稳定性
    有两个相同的数据,在排序前后的前后顺序不变。它与时间复杂度和空间复杂度可以用来的衡量算法的好坏。

2.插入排序

2.1直接插入排序

  1. 将待排数据按其关键码的大小插入到一个有序序列中,最终将所有数据插入序列中,形成一个新的有序序列。

  2. 边插入边排序
    在这里插入图片描述

  3. 代码实现

//直接插入排序(以排升序为例子)
void InsertSort(int* arr,int n)
{
	//思路:从第二个数开始,逐个对有序序列排序
	int i = 0;
	for (i = 1; i < n; i++)
	{
		int end = i - 1;//前面有序序列的最后一个元素
		int tmp = arr[i];
		while (end >= 0)
		{
			if (arr[end] > tmp)//如果有序序列的最后一个元素大于要插入的元素,往后移一位
			{
				arr[end + 1] = arr[end];
				end--;
			}
			else//最后一个元素小于或者等于要插入的元素,跳出循环
			{
				break;
			}
		}
		//遇到特殊情况:要插入元素小于有序序列中的任何元素
		arr[end + 1] = tmp;//既能处理要插入元素比前一个大的情况,又能处理end<0的情况
	}
}
  1. 分析
    时间复杂度
    最好情况下,数据本就是有序的,每次只需与前一个元素比较一次即可,时间复杂度是O(N);最坏情况下,第i趟比较i次,且移动i+1次,时间复杂度是O(N^2)
    空间复杂度
    只有开辟一个额外临时空间。空间复杂度是O(1)
    稳定性
    上面的例子中有相同的12,能保证后面的12始终在后面。是一种稳定的算法
    缺点
    比较次数过多,影响效率。所以就有了折半插入排序。

2.2折半插入法

  1. 思想
    在有序序列中寻找中间进行比较,减少比较次数。
  2. 展示
    在这里插入图片描述
  3. 代码实现
//折半插入法(以升序为例)
void BInsertSort(int* arr, int n)
{
	for (int i = 1; i < n; i++)
	{
		int tmp = arr[i];
		int left = 0;
		int right = i - 1;
		while (left <= right)
		{
			int mid = (left + right) / 2;
			if (arr[mid] > arr[i])
			{
				right = mid - 1;
			}
			else
			{
				left = mid + 1;
			}
		}
		for (int j = i - 1; j >= left; j--)
		{
			arr[j + 1] = arr[j];
		}
		arr[left] = tmp;
	}
}
  1. 分析
    时间复杂度
    在最好情况下,也就是数据是有序时,还是要进行折半比较,比较次数相交于直接插入多;在最坏情况下,比较次数减少明显,在logN这个量级。但是移动次数保持不变,所以时间复杂度依旧是O(N^2)。
    空间复杂度
    只申请一个额外空间。空间复杂度是O(1)。
    稳定性
    在排序前后两个相等的数据前后顺序不变。

2.3希尔排序

  1. 思想
    首先先对数据进行分组,将每组进行直接插入排序,这是预排序。待数据基本有序时,就对全体数据进行直接插入排序。

  2. 例子
    在这里插入图片描述

  3. 疑惑
    那我们要如何确定gap的大小?gap减少到多少时可以算基本有序?
    这个没有明确规定。gap越大,数据跳得越快,越不接近有序,gap越小,数据跳得越慢,越接近有序。gap是个渐变的数,越来越小,最后必须为1。这样才能保证数据最终为有序。gap一般为数据的数目,再以1/2的倍数在减小。

  4. 代码实现

//希尔排序
void ShellSort(int* arr, int n)
{
	int gap = n;
	while (gap > 1)
	{
		//gap /= 2;
		gap = gap / 3 + 1;//+1保证最后进行一次排序是直接插入排序
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = arr[i + gap];
			while (end >= 0)
			{
				if (tmp < arr[end])
				{
					arr[end + gap] = arr[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			arr[end + gap] = tmp;
		}
	}
}
  1. 算法分析
    时间 复杂度
    最外层的while循环的时间复杂度是O(logN),因为N是以1/2在减少。在for循环刚开始时,gap很大,当gap=n/3+1时,for的执行次数是n/3,for里面的while的执行次数为1+2+3 = 6(以最坏情况看),所以第一次循环的时间复杂度是6*(n/3) = 2n。第二次循环,gap接近于n/9,此时for循环的执行次数是n/9,for里面的while的执行次数是1+2+……+9 = 45,所以第二次循环的执行次数是45*(n/9) = 5n。(但实际上要小于5n,因为上次循环数据已经比原先接近有序,所以还要考虑上一轮排序的影响)。当gap最终为1时,因为经过前面多轮的预排序,数据已经接近有序,可以近似于有序序列的排序,所以时间复杂度是O(N)。
    综上,根据大量资料可得,希尔排序的时间复杂度是O(n^1.25)~O(1.6n ^1.25),仍然是处于O(NlongN)这个量级,所以时间复杂度是O(NlogN)。
    空间复杂度
    仅开辟一个额外空间,所以空间复杂度是O(1)。
    稳定性
    这是一个不稳定的排序。因为会对数据进行分组,相同的数据在不同的组里面的最终顺序不同,可能导致最后两者的前后顺序不同。
    注意
    在数据接近有序时,直接插入排序的效率比这版插入排序和希尔排序的效率要高。

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

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

相关文章

ASEMI代理ADI亚德诺LTC6992IS6-1#TRMPBF车规级芯片

编辑-Z LTC6992IS6-1#TRMPBF参数描述&#xff1a; 型号&#xff1a;LTC6992IS6-1#TRMPBF 输出频率&#xff1a;3.81Hz 工作电源电压范围&#xff1a;2.25 - 5.5V 通电复位电压&#xff1a;1.95V 电源电流&#xff1a;105-365A SET引脚处的电压&#xff1a;1V 频率设置电…

性能测试工程师岗分级(初中高/资深/专家)?提高性能测试的价值...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 性能测试岗位按照…

嵌入式Linux驱动开发(十二)platform设备驱动实验

1. platform设备驱动简介 基于驱动可重用性考虑&#xff0c;提出驱动分离与分层思想。平台设备驱动就是基于此。 1.1 驱动分隔与分层 1&#xff09;驱动分隔&#xff1a;   以I2C驱动为例&#xff0c;假设有三类SOC&#xff0c;各自对一个设备写I2C驱动&#xff0c;就需要3…

StarUML破解失败解决办法

明明以及安装了asar但是输入反编译命令还是显示asar不是内部命令 于是根据提示找到了这个文件夹&#xff0c;发现里面有asar的命令&#xff0c;而且输入asar -v也可以查看版本 于是我把app.asar那个文件复制过来了&#xff0c;然后在这个路径输入反编译命令&#xff0c;成功…

6.2.2邻接表法 6.2.3十字链表,邻接多重表

由于用邻接矩阵存储稀疏图会造成大量空间浪费。 而本节课我们所学的邻接表是采用顺序存储加上链式存储的方式。 arcnum指的是弧的数量 对比&#xff1a;树的孩子表示法&#xff08;相同的实现方式&#xff09; Compare&#xff1a; 6.2.3十字链表&#xff0c;邻接多重表 定义这…

Android 内存分析(java/native heap内存、虚拟内存、处理器内存 )

1.jvm 堆内存(dalvik 堆内存) 不同手机中app进程的 jvm 堆内存是不同的&#xff0c;因厂商在出厂设备时会自定义设置其峰值。比如,在Android Studio 创建模拟器时&#xff0c;会设置jvm heap 默认384m , 如下图所示&#xff1a; 当app 进程中java 层 new 对象(加起来总和)占用…

知识图谱实战应用8-从文本关系抽取到知识图谱关系构建流程贯通

大家好,我是微学AI,今天给大家介绍一下知识图谱实战应用8-从文本关系抽取到知识图谱关系构建流程贯通。我们从文本数据中采集到关键信息,并抽取出其中的关系信息,然后在存入图数据库中,整个过程实现自动化,我这里将举一个文本例子进行抽取。 对于知识图谱的构建是将实体…

ThingsBoard使用jar包自己构建镜像部署

1、概述 这一节主要讲解你自己使用jar包构建镜像,一般在很多企业中,都是使用Jenkins配置流水线,自动打包,然后拷贝程序在target目录下生成的jar包,然后使用Dockerfile文件进行构建镜像,其实我这一节讲的也是类似,只是不使用Jenkins来实现自动,原理都一样,估计也是很多…

网络协议 — BGP 边界网关协议

目录 文章目录 目录BGP 和 ASBGP Router 和 RoutesBGP Message 类型和格式BGP Msg HeaderBGP Msg DataOpen MsgKeepalive MsgNotification MsgRoute-refresh MsgUpdate Msg BGP Msg 状态机 BGP RR&#xff08;Route-Reflectors&#xff0c;路由反射器&#xff09;BGP MP&#x…

基于STM32+NBIOT+华为云IOT设计的智能井盖

一、概述 智能井盖是一种通过物联网技术实现对井盖状态监测和管理的设备。当前介绍基于STM32微控制器,BC26 NBIOT模组以及华为云IOT平台设计一款智能井盖系统。该系统通过光线传感器、霍尔传感器、温湿度传感器等设备实现井盖状态的实时监测,通过NBIOT网络将数据上传到华为云…

5 Redis缓存穿透、击穿、雪崩、分布式锁、布隆过滤器

1 Redis 应用问题解决 1.1 缓存穿透 1.1.1 问题描述 key 对应的数据在数据源并不存在&#xff0c;每次针对此 key 的请求从缓存获取不到&#xff0c;请求都会压到数据源&#xff08;数据库&#xff09;&#xff0c;从而可能压垮数据源。比如 用一个不存在的用户 id 获取用户…

ES的概述

一、ECMASript 相关介绍 1.1什么是 ECMA ECMA &#xff08; European Computer Manufacturers Association &#xff09;中文名称为欧洲计算机制 造商协会&#xff0c;这个组织的目标是评估、开发和认可电信和计算机标准。 1994 年后该 组织改名为 Ecma 国际。 1.2.什么…

Three.js--》模型材质与纹理的使用

目录 初识材质与纹理 修改模型材质颜色 模型添加纹理 纹理常用属性使用 纹理显示算法 设置粗糙度 纹理加载进度情况 设置环境贴图 初识材质与纹理 three.js中的材质就是几何体表面的材料。所有材质均继承自Material。ThreeJS的材质分为&#xff1a;基础材质、深度材质…

Linux(centos 7) 环境安装MySQL5.7

mysql安装包 链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;b8w4 环境准备 安装好的centos 7系统 root 用户登录Linux 在根目录下创建/soft目录 上传mysql安装包到/soft目录&#xff0c;结果如下 准备完毕 安装 根据现有序号挨个安装 rpm 包&#xff0c;依…

“聪明车”接驳“智慧路”—— 智能网联车驶上新赛道

去年底&#xff0c;智己L7首批200台Beta体验版下线交付。 智能网联车&#xff0c;“新赛道”上疾驶着“新终端”。“聪明车”如何更好接驳“智慧路”&#xff1f;全国两会现场&#xff0c;不少代表委员聚焦于这一话题展开热议&#xff0c;出谋划策。 “只有把‘终端’牢牢掌握在…

06 - 2 分层架构模式(Layered Arch)

层 层的定义 层&#xff1a;软件的逻辑单元每一层都有特定的功能组件被分配到不同的层 何谓分层 将系统按照职责拆分和组织上层依赖于直接下层 下层不可以依赖于上层不可以跃层访问&#xff08;理想状况&#xff09; 经典分层架构 OSI 7 层架构 CS 两层架构Client&…

生动形象的傅里叶变换解析!

使用联想链条和几何直观&#xff0c;辅以从实际需求衍生概念的思考模式&#xff0c;详解什么是傅立叶变换&#xff0c;为什么要做傅立叶变换等&#xff0c;帮助记忆和理解&#xff0c;目的当然是标题所说&#xff1a;让你永远忘不了傅里叶变换这个公式。另&#xff0c;这篇博客…

MySQL之Server层的内存结构

前言 本文已收录在MySQL性能优化原理实战专栏&#xff0c;点击此处浏览更多优质内容。 前面的文章我们介绍了InnoDB存储引擎的一些内存、内存磁盘的结构以及工作原理&#xff0c;今天我们就来看一下关于MySQL Server层的一些内存结构。 目录 一、Binlog Cache1.1 Binlog Cache工…

jvm之远程调试

写在前面 工作中&#xff0c;有时会出现测试环境有问题&#xff0c;本地却正常的情况&#xff0c;此时我们就可以通过JVM提供的远程调用的功能&#xff0c;实现在本地debug调试测试环境代码。 1&#xff1a;例子1直接运行class 首先我们来定义类&#xff1a; package com.f…

Blender 形变类修改器:曲线

目录 形变类修改器1. 测试一&#xff1a;减少环切数量1.1 调整物体原点1.2 让两个物体原点重合1.3 添加曲线修改器1.4 融并边 2. 测试二&#xff1a;曲线的方向2.1 查看曲线的方向&#xff08;曲线法向显示&#xff09;2.2 在3D空间调整曲线 3. 测试三&#xff1a;空间位置的影…