插入排序⁻⁻⁻⁻直接插入排序希尔排序

news2025/2/24 12:28:47

引言

所谓的排序,就是使一串记录按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。

常见的排序算法有:

e3e60e163ea7413f838b5726d259905c.png

 今天我们主要学习插入排序的直接插入排序和希尔排序。

直接插入排序

什么是直接插入排序?

直接插入排序其实是一种很简单的排序算法哦。它就像我们平时整理扑克牌一样,一张一张地来,把每一张牌都插到已经排好序的部分里面,直到全部都排好。

25e59251b7514f12b92286c26ea56488.jpg

 我们再通过一个动图理解一下:

d9a74a8eea15476ab53c4a67b1f13c59.gif

思路

  1. 从第二个元素始,逐一遍历数组。
  2. 当前元素与前序已排序元素逐一比较,找到插入位置。
  3. 插入当前元素至正确位置,前序元素后移。
  4. 重复上述步骤,直至数组全排序。

代码

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

时间复杂度

从代码我们可以看出,直接插入排序的时间复杂度是 O(n²),在数据比较少或者已经部分有序的情况下,它的性能还是不错的。

希尔排序

什么是希尔排序?

希尔排序,又称为缩小增量排序,是直接插入排序的一种更高效的改进版本。

前面我们知道,直接插入排序比最差的条件下时间复杂度可以达到O(n²),但是在部分有序的情况下,它的性能还是不错的。

希尔排序的基本思想是预排序,即先将数组内的数据变得部分有序,最后再通过直接插入排序将部分有序的数组进组排序。

那它具体是如何实现预排序的呢?接下来我们会进行讲解。

讲解与分析

接下来,我们具体来通过一个例子来理解一下希尔排序:先将整个待排序数组分割成若干个子序列(也称为分组),使得每个子序列中的元素在原数组中的位置间隔gap,然后对每个子序列分别进行直接插入排序,这样可以使原数组变得部分有序。我们一起来看一下:

原数组:int a[]={9,1,2,5,7,4,8,6,3,5};

接下来我们按照间隔(gap)为3时将原数组进行升序排序,什么意思呢?即下标为0,3,6,9的树为一组进行排序,对应上面的数组也就是将9,5,8,5进行排序:

5579b018902a40e68b9beac14d0ea6ec.png

 

tmp之前的数据已经按升序排序,开始进入下一轮排序:

fe848e964700402d8b947fddcca138c5.png

 

tmp之前的数据已经按升序排序,开始进行下一轮排序:

17f71b1b965e438d841c3e6e46f9e32d.jpg

如果我们让gap为2,原数组排序下来会是这样的:1cefbaf4c52c40228cc8cd13e1beeea7.png

 我们发现,gap越大,排序就越快,但是越不接近有序;gap越小,排序就越慢,但是越接近有序。

当gap等于1就是直接插入排序,gap大于1就是预排序。

那我们可以先让gap初始化为较大的数,我们可以逐渐缩小gap,再对新的子序列进行直接插入排序,直到最后增量减至1,此时整个数组几乎已经有序,最后再进行一次直接插入排序即可完成排序。

这里补充说明一下gap的初始值,一般初始化为数组长的一半或三分之一。如果是数组长度的二分之一,每次gap就是按照gap/=2去缩小;如果是数组长的三分之一,每次gap就是按照gap=gap/3+1去缩小(为什么不是gap/=3呢?我们要考虑到两个整数相除时,最后结果会向下取整,如果数组长度n=6,第一次排序时gap=n/3=2,第二次排序时gap/=3就是2/3=0,那这样下去永远都无法让gap==1,也就无法进行直接插入排序。所以应该是gap=gap/3+1)。

代码

void shellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1) {
		gap = gap / 3 + 1;
		for (int i = 0; i < n - gap; i += gap) {
			int curIndex = i, tmp = a[i + gap];
			while (curIndex >= 0) {
				if (tmp < a[curIndex]) {
					a[curIndex + gap] = a[curIndex];
					curIndex -= gap;
				}
				else {
					break;
				}
			}
			a[curIndex + gap] = tmp;
		}
	}
	
}

时间复杂度

分析

  • 最外层循环:控制间隔(gap)的变化,通常从数组长度n开始,每次除以一个常数(如3)并加1,直到gap为1。此循环的时间复杂度为O(logn)。
  • 内层循环(这种分析方式存在一定不严谨性):包括两层循环,一层用于遍历数组,另一层用于在分组内进行插入排序。for循环以gap为步长遍历数组,因此其迭代次数为n / gap次。在每次for循环的迭代中,while循环负责将当前元素(位于i + gap位置)插入到其前面gap间隔的有序子序列中。最坏情况下,这个插入操作需要比较和移动gap个元素(但实际上由于分组的存在,通常不会达到这么多)。然而,对于时间复杂度的分析,我们可以认为每次while循环至多执行O(gap)次操作,但在整个for循环中,由于分组的存在,每个元素至多被比较和移动一次。因此,对于每个固定的gap值,内层循环(包括for和while)的总时间复杂度为O(n)。

注意:严谨的内层循环时间复杂度分析

1.gap较大时:

  • 当gap较大时,数组被分成较少的组,每组包含较多的元素。
  • 由于此时数组尚未排序,每组内的插入排序可能需要进行较多的比较和交换。
  • 但由于组数较少,整体时间复杂度相对较低。

2.gap逐渐减小时:

  • 随着gap的减小,数组被分成更多的组,每组包含的元素减少。
  • 由于前面的排序过程,数组已经逐渐接近有序状态,因此每组内的插入排序所需的比较和交换次数减少。
  • 此时,虽然组数增多,但每组内的排序工作量减少,整体时间复杂度仍然保持较低水平。

3.gap变化过程中的复杂度峰值:

  • 在gap从大到小变化的过程中,存在一个复杂度峰值。这是因为当gap处于某个中间值时,数组既没有被完全分组(如gap很大时),也没有接近有序(如gap很小时)。
  • 在这个峰值点,每组内的插入排序可能需要较多的比较和交换,导致时间复杂度相对较高。

综合时间复杂度

希尔排序的时间复杂度不是简单的O(nlogn),因为间隔的变化会影响排序的效率。

在某些情况下,希尔排序的时间复杂度可以接近O(nlogn),特别是在数组已经部分有序或间隔选择得当的情况下。

然而,在最坏情况下,希尔排序的时间复杂度可能更高,一些研究表明其时间复杂度在O(n^1.25)到O(n^1.6)之间,通常可以简化为O(n^1.3)。

 

 

 

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

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

相关文章

Python实现中国象棋

探索中国象棋 Python 代码实现&#xff1a;从规则逻辑到游戏呈现 中国象棋&#xff0c;这款源远流长的棋类游戏&#xff0c;承载着深厚的文化底蕴与策略智慧。如今&#xff0c;借助 Python 与 Pygame 库&#xff0c;我们能够在数字世界中复刻其魅力&#xff0c;深入探究代码背后…

2024年12月6日Github流行趋势

项目名称&#xff1a;lobe-chat 项目维护者&#xff1a;arvinxx, semantic-release-bot, canisminor1990, lobehubbot, renovate项目介绍&#xff1a;一个开源的现代化设计的人工智能聊天框架。支持多AI供应商&#xff08;OpenAI / Claude 3 / Gemini / Ollama / Qwen / DeepSe…

FastAPI 响应状态码:管理和自定义 HTTP Status Code

FastAPI 响应状态码&#xff1a;管理和自定义 HTTP Status Code 本文介绍了如何在 FastAPI 中声明、使用和修改 HTTP 状态码&#xff0c;涵盖了常见的 HTTP 状态码分类&#xff0c;如信息响应&#xff08;1xx&#xff09;、成功状态&#xff08;2xx&#xff09;、客户端错误&a…

AWS 机器学习,推动 AI 技术的健康发展

目录 一、AI 正在改变生产方式二、从炒作走向务实1、选对场景2、重视数据3、产品思维4、持续优化 三、人才是最稀缺的资源四、负责任的 AI 开发五、未来已来六、启示与思考七、结语 如果说传统软件开发是手工作坊&#xff0c;那么 AI 就像工业革命带来的机器生产。 在最新的一…

OceanBase 的探索与实践

作者&#xff1a;来自 vivo 互联网数据库团队- Xu Shaohui 本文总结了目前我们遇到的痛点问题并通过 OceanBase 的技术方案解决了这些痛点问题&#xff0c;完整的描述了 OceanBase 的实施落地&#xff0c;通过迁移到 OceanBase 实践案例中遇到的问题与解决方案让大家能更好的了…

Nginx安装和配置详解

1.Nginx的安装 1.1运行以下脚本安装 yum install yum-utils -y rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm# 查看所有可安装nginx版本 yum --showduplicates list available nginx yum install nginx-1.24.0 -y …

up主亲测,ToDesk/青椒云/顺网云这三款云电脑玩转AIGC场景

文章目录 1. 前言2. 云电脑性能分析3. 基础硬件数据3.1 硬件配置3.2 AI 评测跑分 4. 云电脑 AIGC 上手实测4.1 ToDesk4.1.1 AIGC 技术集成情况4.1.2 界面及功能4.1.3 项目部署4.1.4 黑神话悟空 AI 换脸4.1.6 AIGC 文生图体验 4.2 青椒云4.2.1 AIGC 技术集成情况4.2.2 界面及功能…

ARM架构-Cache的底层原理

在主存与处理器之间加入一个小容量的存储器保存 CPU 最近一段时间内的历史访问数据&#xff0c;将在 CPU 发起访问的时候优先提供数据快速访问&#xff0c;这个介于 CPU 与主存储器之间的小容量高速存储空间我们称之为 Cache&#xff0c;即高速缓存。Cache 作为处理器与主存之间…

Codeforces Round 991 (Div. 3) F. Maximum modulo equality(区间gcd模板)

思路&#xff1a;我们由题意可以知道我们只需要维护区间gcd即可&#xff0c;因为差分一下后&#xff0c;维护的差分数组的区间gcd即为原数组所要求的值 线段树维护 #include<bits/stdc.h>using namespace std;typedef long long ll; typedef pair<ll, ll>PII; co…

树与图深度优先遍历——acwing

题目一&#xff1a;树的重心 846. 树的重心 - AcWing题库 分析 采用暴力枚举&#xff0c;试探每个点&#xff0c;除去之后&#xff0c;连通分量最大值是多少&#xff0c; 各个点的最大值找最小的 因为可以通过 dfs 来得到 根u以下点数&#xff0c;以及可以求各分树的点数&am…

消息中间件-Kafka3-kafkaJavaClient小例

消息中间件-Kafka3-kafkaJavaClient小例 Kafak Java Client private static final String KAFKA_TOPIC "kafak-test";private static String bootstrapServers "localhost:9092";private static AdminClient client null;static {Properties config n…

团队管理中如何做好目标管理

团队管理中的目标管理是确保团队高效运行的核心要素之一。 在目标管理中&#xff0c;清晰的目标设定、合理的资源分配、实时的跟踪与反馈机制是成功的关键。首先&#xff0c;设定SMART目标&#xff08;具体、可衡量、可达成、相关性强、时间限定&#xff09;能够有效聚焦团队的…

【QT】一个简单的串口通信小工具(QSerialPort实现)

目录 0.简介 1.展示结果 1&#xff09;UI界面&#xff1a; 2&#xff09;SSCOM&#xff08;模拟下位机收发&#xff09;&#xff1a; 3&#xff09;VSPD虚拟串口驱动&#xff08;连接上位机和下位机的串口&#xff09;&#xff1a; 4&#xff09;实际收发消息效果及视频演…

灵途科技亮相2024世界传感器大会 分享光纤光源技术突破

12月1日至2日&#xff0c;2024世界传感器大会&#xff08;WSS&#xff09;在郑州国际会展中心隆重举办&#xff0c;泛自动驾驶领域光电感知专家灵途科技受邀参加“光纤传感器与激光雷达”分论坛&#xff0c;并在大会上带来《激光雷达用一体化光纤光源》专题演讲&#xff0c;同与…

12月第1周AI资讯

阅读时间:3-4min 更新时间:2024.12.2-2024.12.6 目录 OpenAI CEO Sam Altman 预告“12天OpenAI”系列活动 腾讯HunyuanVideo:130亿参数的开源视频生成模型 李飞飞的World Labs发布空间智能技术预览版 中科院联手腾讯打造“AI带货王”AnchorCrafter OpenAI CEO Sam Alt…

CentOS7.X 安装RustDesk自建服务器实现远程桌面控制

参照文章CentOS安装RustDesk自建服务器中间总有几个位置出错&#xff0c;经实践做个记录防止遗忘 一 环境&工具准备 1.1 阿里云轻量服务器、Centos7系统、目前最高1.1.11版本rustdesk-server-linux-amd64.zip 1.2 阿里云轻量服务器–安全组–开放端口&#xff1a;TCP(21…

图形开发基础之在WinForms中使用OpenTK.GLControl进行图形绘制

前言 GLControl 是 OpenTK 库中一个重要的控件&#xff0c;专门用于在 Windows Forms 应用程序中集成 OpenGL 图形渲染。通过 GLControl&#xff0c;可以轻松地将 OpenGL 的高性能图形绘制功能嵌入到传统的桌面应用程序中。 1. GLControl 的核心功能 OpenGL 渲染上下文&…

指标加权评价方法

文章目录 层次分析法&#xff08;Analytic Hierarchy Process, AHP&#xff09;熵权法原理计算方法 Technique for Order Preference by Similarity to Ideal Solution(TOPSIS, 优劣解距离法)原理计算方法 层次分析法&#xff08;Analytic Hierarchy Process, AHP&#xff09; …

git管理Unity项目的正确方式

git管理Unity项目的正确打开方式 前言&#xff1a;对于刚开始git进行unity项目管理的时候&#xff0c;我采取的方式是全部文件上传&#xff0c;文件数量太多以及上传太大&#xff0c;我尝试过一下几个方法&#xff1a; 利用git的LFS大文件进行传方式&#xff0c;可行但比较麻…

GitToolBox插件:让IntelliJ IDEA的Git操作如虎添翼

GitToolBox插件介绍 GitToolBox是一款针对IntelliJ IDEA的插件&#xff0c;旨在增强IDE内置的Git功能&#xff0c;使Git操作更加便捷和高效。无论是单独开发者还是团队中的一员&#xff0c;这个插件都能帮助更好地管理代码和协作流程。 功能特点 分支管理&#xff1a;GitToolBo…