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

引言

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

常见的排序算法有:

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.rhkb.cn/news/485706.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙UI开发——亮/暗色模式适配

1、概 述 系统存在深浅色两种显示模式&#xff0c;为了给用户更好的使用体验&#xff0c;应用最好适配暗色和亮色两种模式。从应用与系统配置关联的角度来看&#xff0c;适配暗色和亮色模式可以分为下面两种情况&#xff1a; 应用跟随系统的深浅色模式&#xff1b; 应用主动设…

推荐在线Sql运行

SQL Fiddle 1、网址&#xff1a;SQL Fiddle - Online SQL Compiler for learning & practiceDiscover our free online SQL editor enhanced with AI to chat, explain, and generate code. Support SQL Server, MySQL, MariaDB, PostgreSQL, and SQLite.http://www.sqlfi…

在Ubuntu-22.04 [WSL2]中配置Docker

文章目录 0. 进入Ubuntu-22.041. 更新系统软件包2. 安装Docker相关依赖包3. 添加Docker官方GPG密钥4. 添加Docker软件源5. 安装Docker Engine5.1 更新软件包列表5.2 安装Docker相关软件包 6. 验证Docker安装是否成功6.1 查看Docker版本信息6.2 启动Docker6.3 配置镜像加速器6.4…

AI大模型ollama结合Open-webui

AI大模型Ollama结合Open-webui 作者:行癫(盗版必究) 一:认识 Ollama 1.什么是Ollama ​ Ollama是一个开源的 LLM(大型语言模型)服务工具,用于简化在本地运行大语言模型,降低使用大语言模型的门槛,使得大模型的开发者、研究人员和爱好者能够在本地环境快速实验、管理和…

使用ensp搭建内外互通,使用路由跨不同vlan通信。

1.网络拓扑图 2.规则 &#xff08;1&#xff09;允许 &#xff08;自己&#xff09;ping通内外网&#xff0c;内外网随便一个pc就可以. &#xff08;2&#xff09; 允许&#xff08;电信&#xff09;ping通内外网&#xff0c;内外网随便一个pc就可以 &#xff08;时间问题不做…

gRPC 快速入门 — SpringBoot 实现(1)

目录 一、什么是 RPC 框架 &#xff1f; 二、什么是 gRPC 框架 &#xff1f; 三、传统 RPC 与 gRPC 对比 四、gRPC 的优势和适用场景 五、gRPC 在分布式系统中应用场景 六、什么是 Protocol Buffers&#xff08;ProtoBuf&#xff09;&#xff1f; 特点 使用场景 简单的…

Python实现BBS论坛自动签到【steamtools论坛】

一、知识点分析 1.requests模块介绍 ‌requests模块是Python中用于发送HTTP请求的一个库,它封装了urllib3库,提供了更加便捷的API接口。‌ 通过使用requests模块,用户可以模拟浏览器的请求,发送HTTP请求到指定的URL,并获取响应内容。与urllib相比,requests模块的API更加…

Probabilistic Face Embeddings 论文阅读

Probabilistic Face Embeddings 论文阅读 Abstract1. Introduction2. Related Work3. Limitations of Deterministic Embeddings4. Probabilistic Face Embeddings4.1. Matching with PFEs4.2. Fusion with PFEs4.3. Learning 5. Experiments5.1. Experiments on Different Bas…

重磅升级:OpenAI o1模型上手实测,从芯片架构分析到象棋残局判断的全能表现

引言 昨日&#xff0c;在圣诞节系列发布会的第一天&#xff0c;OpenAI终于给我们带来了令人振奋的更新&#xff0c;这些更新有望塑造AI互动的未来。备受期待的OpenAI o1正式版的推出&#xff0c;标志着ChatGPT体验的重大进化&#xff0c;宣告了AI驱动应用新时代的开始。o1现已可…

1.使用docker 部署redis Cluster模式 集群3主3从

1.使用docker 部署redis Cluster模式 集群3主3从 1.1 先安装docker 启动docker服务&#xff0c;拉取redis镜像 3主3从我们要在docker启动6个容器docker run --name redis-node-1 --net host --privilegedtrue -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluster-…

如何通过 Windows 自带的启动管理功能优化电脑启动程序

在日常使用电脑的过程中&#xff0c;您可能注意到开机后某些程序会自动运行。这些程序被称为“自启动”或“启动项”&#xff0c;它们可以在系统启动时自动加载并开始运行&#xff0c;有时甚至在后台默默工作。虽然一些启动项可能是必要的&#xff08;如杀毒软件&#xff09;&a…

记一次跑前端老项目的问题

记一次跑前端老项目的问题 一、前言二、过程1、下载依赖2、启动项目3、打包 一、前言 在一次跑前端老项目的时候&#xff0c;遇到了一些坑&#xff0c;这里记录一下。 二、过程 1、下载依赖 使用 npm install下载很久&#xff0c;然后给我报了个错 core-js2.6.12: core-js…

在米尔FPGA开发板上实现Tiny YOLO V4,助力AIoT应用

学习如何在 MYIR 的 ZU3EG FPGA 开发板上部署 Tiny YOLO v4&#xff0c;对比 FPGA、GPU、CPU 的性能&#xff0c;助力 AIoT 边缘计算应用。 一、 为什么选择 FPGA&#xff1a;应对 7nm 制程与 AI 限制 在全球半导体制程限制和高端 GPU 受限的大环境下&#xff0c;FPGA 成为了中…

Python爬虫之selenium库驱动浏览器

目录 一、简介 二、使用selenium库前的准备 1、了解selenium库驱动浏览器的原理 &#xff08;1&#xff09;、WebDriver 协议 &#xff08;2&#xff09;、 浏览器驱动&#xff08;Browser Driver&#xff09; &#xff08;3&#xff09;、 Selenium 客户端库 &#xff0…

从零开始学TiDB(2)深入了解TiDB Server模块

TiDB Server 架构 TiDB Server 的主要功能&#xff1a; 一条SQL的执行流程&#xff1a; 1.将整个SQL语句解析成一个个的token&#xff0c;生成一个树形结构。 2.编译模块 1.首先需要做一个合法性验证&#xff0c;比如表存不存在等。 2.做逻辑优化&#xff1a;依据关系型代数等…

dbnet轻型网络文本检测 - python 实现

DataBall 助力快速掌握数据集的信息和使用方式&#xff0c;会员享有 百种数据集&#xff0c;持续增加中。 需要更多数据资源和技术解决方案&#xff0c;知识星球&#xff1a; “DataBall - X 数据球(free)” -------------------------------------------------------------…

玩《三角洲行动》遇到游戏运行故障是什么原因?游戏运行故障要怎么解决?预防游戏运行故障问题出现

《三角洲行动》游戏运行故障解析与解决方案&#xff1a;原因、解决与预防 在畅游《三角洲行动》这款充满挑战与激情的游戏时&#xff0c;玩家可能会遭遇各种游戏运行故障&#xff0c;如卡顿、闪退、无法启动等问题。我将结合自己丰富的经验和知识&#xff0c;为大家深入剖析《…

【Axure高保真原型】数值条件分组

今天和大家分享数值条件分组的原型模板&#xff0c;效果包括&#xff1a; 点击添加分组按钮&#xff0c;可以显示添加弹窗&#xff0c;填写分组名称和数值区间后&#xff0c;可以新增该分组信息‘’ 修改分组区间&#xff0c;可以直接在输入框里修改已有的分组区间&#xff0c…

「Mac畅玩鸿蒙与硬件40」UI互动应用篇17 - 照片墙布局

本篇将带你实现一个简单的照片墙布局应用&#xff0c;通过展示多张图片组成照片墙效果&#xff0c;用户可以点击图片查看其状态变化。 关键词 UI互动应用照片墙布局Grid 布局动态图片加载用户交互 一、功能说明 照片墙布局应用的特点&#xff1a; 动态加载多张图片组成网格布…

【Golang】Golang基础语法之面向对象:结构体和方法

面向对象——结构 Go 仅支持封装&#xff0c;不支持继承和多态&#xff1b;继承和多态要做的事情交给接口来完成&#xff0c;即——面向接口编程。Go 只有 struct&#xff0c;没有 class。 定义一个最简单的树节点&#xff08;treeNode&#xff09;结构&#xff0c;方法如下&…