数据结构——排序(插入排序)

目录

一、插入排序

二、直接插入排序

基本概念:

工作原理:

示例:

    代码实现

三、希尔排序

(一)基本概念

(二)工作原理

(三)示例

(四)代码实现

一、插入排序

插入排序是一种简单且直观的排序算法,在实际应用和算法学习中都具有重要地位。它主要分为直接插入排序和希尔排序两种形式,每种都有其独特的特点和应用场景。


二、直接插入排序

  1. 基本概念

    • 直接插入排序是一种简单的排序算法,它的基本思想是将一个未排序的数据元素逐个插入到已排好序的部分序列中,直到整个序列都变为有序。
    • 就像整理手中的扑克牌一样,每次拿到一张新牌,将其插入到已整理好的牌堆中的合适位置,使得牌堆始终保持有序。
  2. 工作原理

    • 从数组的第二个元素开始,将其视为待插入的元素。
    • 与已排好序的部分序列(通常是数组的前一个或前几个元素)进行比较,找到合适的位置插入该元素。
    • 重复这个过程,直到所有元素都被插入到正确的位置,此时数组就变为有序的了。
  3. 示例

    • 例如有数组 [5, 3, 8, 4, 2]。
    • 首先,认为第一个元素 5 是已排好序的部分序列。
    • 然后处理第二个元素 3,将 3 与 5 比较,发现 3 小于 5,将 3 插入到 5 的前面,此时数组变为 [3, 5, 8, 4, 2]。
    • 接着处理第三个元素 8,由于 8 大于已排好序部分序列的最后一个元素 5,所以直接将 8 放在合适位置,数组仍为 [3, 5, 8, 4, 2]。
    • 再处理第四个元素 4,将 4 与 8、5 依次比较,插入到 5 的后面,数组变为 [3, 4, 5, 8, 2]。
    • 最后处理第五个元素 2,经过比较插入到最前面,数组变为 [2, 3, 4, 5, 8],排序完成。

    代码实现

InsertSort函数详解

  1. 外层循环

    • for (int i = 0; i < n - 1; ++i)循环遍历数组中除最后一个元素之外的所有元素。这个循环的作用是逐步扩大已排好序的部分序列。
    • 每次循环中,变量end被初始化为i,表示当前已排好序部分序列的最后一个位置。
  2. 内层循环与插入操作

    • int tmp = a[end + 1];将待插入的元素(即当前未排序部分的第一个元素)存储在tmp中。
    • while (end >= 0)开始一个内层循环,只要end不小于 0,就继续循环。这个循环的目的是在已排好序的部分序列中找到待插入元素的正确位置。
    • if (a[end] > tmp)如果当前已排好序部分的元素大于待插入元素,就将该元素向后移动一位,即a[end + 1] = a[end];,然后递减end继续比较前一个元素。
    • else当找到一个不大于tmp的位置或者遍历到数组的开头时,跳出循环。
    • a[end + 1] = tmp;将待插入元素插入到正确的位置。
void InsertSort(int* a, int n)
{// [0, end]有序  end+1位置的值插入[0, end],让[0, end+1]有序//这个循环遍历数组中除最后一个元素之外的所有元素。for (int i = 0; i < n - 1; ++i){int end = i ;int tmp = a[end + 1];while (end >=0){if (a[end] > tmp){a[end + 1] = a[end];--end;}//当找到一个不大于tmp的位置或者遍历到数组的开头时,跳出循环else{break;}}a[end + 1] = tmp;}
}

三、希尔排序

(一)基本概念

希尔排序是对直接插入排序的改进,也称为缩小增量排序。它通过将数据分成若干个较小的子序列,对每个子序列进行插入排序,然后逐步减少子序列的数量和间隔,最终对整个序列进行一次直接插入排序,使得整个序列基本有序,从而提高排序效率。

(二)工作原理

  1. 首先确定一个初始的间隔(增量),一般初始间隔可以取数组长度的一半。
  2. 将数组按照间隔分成若干个子序列。例如,间隔为 3 时,对于数组 [1, 2, 3, 4, 5, 6, 7, 8, 9],会分成 [1, 4, 7]、[2, 5, 8]、[3, 6, 9] 等子序列。
  3. 对每个子序列分别进行直接插入排序。
  4. 然后逐渐减小间隔,重复步骤 2 和 3,直到间隔减小到 1。此时,整个数组基本有序,再进行一次直接插入排序就可以得到完全有序的序列。

(三)示例

以数组 [9, 8, 7, 6, 5, 4, 3, 2, 1] 为例,初始间隔为 4:

  • 第一轮,间隔为 4:
    • 子序列 [9, 5, 1],进行插入排序后变为 [1, 5, 9]。
    • 子序列 [8, 4, 2],排序后变为 [2, 4, 8]。
    • 子序列 [7, 3],排序后变为 [3, 7]。
    • 子序列 [6] 不变。
    • 此时数组变为 [1, 2, 3, 6, 5, 4, 7, 8, 9]。
  • 第二轮,间隔为 2:
    • 子序列 [1, 3, 5, 7, 9],排序后变为 [1, 3, 5, 7, 9]。
    • 子序列 [2, 4, 6, 8],排序后变为 [2, 4, 6, 8]。
    • 数组变为 [1, 2, 3, 4, 5, 6, 7, 8, 9]。
  • 第三轮,间隔为 1,进行直接插入排序,此时数组已经基本有序,排序后仍为 [1, 2, 3, 4, 5, 6, 7, 8, 9],排序完成。

(四)代码实现

主要步骤解释

  1. 确定初始间隔并循环

    • int gap = n;初始化间隔为数组的长度n
    • while (gap > 1)循环条件确保在间隔大于 1 时进行预排序操作。每次循环都会将间隔逐渐缩小,直到间隔变为 1,此时进行直接插入排序以确保数组完全有序。
  2. 设置间隔策略

    • gap /= 2;这里采用了简单的间隔减半策略。也可以使用其他策略,如gap = gap / 3 + 1;以不同的方式调整间隔,不同的策略可能会影响算法的性能。
  3. 多组数据同时预排序

    • for (int i = 0; i < n - gap; ++i)外层循环遍历数组,从第一个元素开始,每次处理一组间隔为gap的数据。
    • int end = i;int tmp = a[end + gap];与直接插入排序类似,保存当前待插入元素和其对应的索引。
    • while (end >= 0)内层循环在已处理的部分中找到待插入元素的正确位置。如果当前元素大于待插入元素,就将当前元素向后移动gap位,然后继续向前比较。当找到合适位置或遍历到数组开头时,跳出循环。
    • a[end + gap] = tmp;将待插入元素插入到正确的位置。
//希尔排序
void ShellSort(int* a, int n)
{int gap = n;while (gap>1)//gap > 1时都是预排序,接近有序;gap == 1时就是直接插入排序 有序{gap /= 2; // logN,gap/2一定会最后除成1//gap = gap / 3 + 1;而gap/3不会,所以最后加个1;log3N 以3为底数的对数// gap很大时,下面预排序时间复杂度O(N)// gap很小时,数组已经很接近有序了,这时差不多也是(N)// 把间隔为gap的多组数据同时排,gap由大变小,//gap越大,大的数可以更快的排在后面,小的数可以更快的排在前面,gap越大,预排完越不接近有序//gap越小,越接近有序for (int i = 0; i < n - gap; ++i){int end = i;int tmp = a[end + gap];while (end >= 0)//数组下标从0开始{if (a[end] > tmp){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}
}

四、两者比较

  1. 排序思想有共通点
    • 两者都是基于插入的思想进行排序。直接插入排序是将未排序的元素逐个插入到已排好序的部分中,而希尔排序也是通过不断地将元素插入到相对有序的子序列中,逐步使整个数组有序。
    • 在实现过程中,都有一个类似的内层循环用于寻找待插入元素的正确位置。在这个循环中,都是通过比较当前元素与待插入元素的大小,决定是否进行元素的移动。
  2. 时间复杂度不同
    • 直接插入排序在最坏情况下的时间复杂度为 ,对于小规模数据或基本有序的数据排序效率较高,但对于大规模无序数据,性能可能较差。
    • 希尔排序的时间复杂度取决于间隔序列的选择,一般在一些情况下可以达到  左右,虽然最坏情况下时间复杂度仍然为 ,但平均性能比直接插入排序更好,尤其对于大规模数据。
  3. 初始状态和循环条件不同
    • 在直接插入排序函数中,外层循环从数组的第一个元素开始,逐步处理到倒数第二个元素,因为最后一个元素不需要进行插入操作。内层循环的条件是已排好序部分的索引end大于等于 0,只要还没有遍历到数组的开头,就继续比较和移动元素。
    • 希尔排序函数中,外层循环的条件是间隔gap大于 1,通过不断减小gap来逐步进行预排序。在每次外层循环中,都会对间隔为gap的子序列进行处理。内层循环的条件和直接插入排序类似,但处理的是间隔为gap的元素。

总体而言,希尔排序是对直接插入排序的改进,通过更复杂的排序策略,在处理大规模数据时具有更好的性能。而直接插入排序则更加简单直观,适用于小规模或基本有序的数据。

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

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

相关文章

120页满分PPT | 企业级业务架构和IT架构规划方案

方案内容综述 方案涵盖了从战略分析到具体实施路径的内容。提出了IT架构规划的工作思路&#xff0c;包括项目启动、部门访谈、资料收集、内部数据库搜索与先进实践研究等步骤&#xff0c;旨在通过这些步骤完成现状及差距分析&#xff0c;并基于此设计未来的应用架构、数据架构…

算法:724.寻找数组的中心下标

题目 链接&#xff1a;leetcode链接 思路分析&#xff08;前缀和&#xff09; 根据题意&#xff0c;我们可以将数组看成三个部分 [left] [mid] [right] 我们只需要[left]区间内的元素和等于[right]区间的元素和即可&#xff0c;此时mid就是中心下标 那么我们可以借助前缀和思…

鸿蒙开发之ArkUI 界面篇 二十 position绝对定位及层级zIndex

position控制组件的位置&#xff0c;可以实现层叠效果&#xff0c;Android中的FramLayout,通常用在左上角有些图标之类&#xff0c;绝对定位后的组件不占用自身原有位置,每个子组件都有这个属性&#xff0c;只是不用这个属性的时候不起作用&#xff0c;.zIndex()属性要和positi…

微服务——分布式事务

目录 分布式事务 1.1分布式事务的特性 1.2分布式事务应用背景 ​编辑 1.3.认识Seata 1.4部署TC服务 1.4.1.准备数据库表 1.4.2.准备配置文件 1.4.3.Docker部署 1.5.微服务集成Seata 1.5.1.引入依赖 1.5.2.改造配置 1.5.3.添加数据库表 ​编辑1.6.XA模式 1.6.1.两…

聊聊Mysql的MVCC

1 什么是MVCC&#xff1f; MVCC&#xff0c;是Multiversion Concurrency Control的缩写&#xff0c;翻译过来是多版本并发控制&#xff0c;和数据库锁一样&#xff0c;他也是一种并发控制的解决方案。 我们知道&#xff0c;在数据库中&#xff0c;对数据的操作主要有2种&#…

【数据结构 | PTA】表

文章目录 7-1 重排链表7-2 链表去重7-3 两个有序链表序列的合并7-4 两个有序链表序列的交集 7-1 重排链表 输入格式&#xff1a; 每个输入包含1个测试用例。每个测试用例第1行给出第1个结点的地址和结点总个数&#xff0c;即正整数N (≤105)。结点的地址是5位非负整数&#xff…

K8s持久化存储PV和PVC(通俗易懂)

一、PV和PVC的引入 Volume 提供了非常好的数据持久化方案,不过在可管理性上还有不足。 拿前面 AWS EBS 的例子来说,要使用 Volume,Pod 必须事先知道如下信息: 当前 Volume 来自 AWS EBS。EBS Volume 已经提前创建,并且知道确切的 volume-id。Pod 通常是由应用的开发人员…

Linux安装配置Jupyter Lab并开机自启

文章目录 1、安装配置jupyter lab首先需要使用pip3安装&#xff1a;生成配置文件和密码&#xff1a; 2、设置开机自启首先通过which jupyter查询到可执行文件路径&#xff1a;设置自启服务&#xff1a; 1、安装配置jupyter lab 首先需要使用pip3安装&#xff1a; pip3 instal…

细说机器学习和深度学习

背景 平常业务开发中每天都要接触到机器学习和深度学习的概念&#xff0c;在听了很多大佬的普及后&#xff0c;发现甚是有趣。于是小编想着着手开始学习这部分的内容。 那废话不多说&#xff0c;就从最基础的机器学习和神经网络开始~ 一、机器学习基础 1、机器学习是什么&a…

2024 uniapp入门教程 01:含有vue3基础 我的第一个uniapp页面

uni-app官网uni-app,uniCloud,serverless,快速体验,看视频&#xff0c;10分钟了解uni-app,为什么要选择uni-app&#xff1f;,功能框架图,一套代码&#xff0c;运行到多个平台https://uniapp.dcloud.net.cn/ 准备工作&#xff1a;HBuilder X 软件 HBuilder X 官网下载&#xf…

职场上的人情世故,你知多少?这五点一定要了解

职场是一个由人组成的复杂社交网络&#xff0c;人情世故在其中起着至关重要的作用。良好的人际关系可以帮助我们更好地融入团队&#xff0c;提升工作效率&#xff0c;甚至影响职业发展。在职场中&#xff0c;我们需要了解一些关键要素&#xff0c;以更好地处理人际关系&#xf…

泛微流程隐藏按钮

隐藏右键菜单的按钮 控制台输入 mobx.toJS(WfForm.getGlobalStore().rightMenu.rightMenus) 获取相对应 type在js中进行隐藏 ecodeSDK.overwritePropsFnQueueMapSet(WeaRightMenu,{ //复写组件名隐藏菜单fn:(newProps)>{ //newProps代表组件参数newProps.datas newProps.…

Hierarchical Cross-Modal Agent for Robotics Vision-and-Language Navigation

题目&#xff1a;用于视觉语言导航的层次化跨模态智能体 摘要 1. 问题背景和现有方法 VLN任务&#xff1a;这是一种复杂的任务&#xff0c;要求智能体基于视觉输入和自然语言指令进行导航。 现有方法的局限性&#xff1a;之前的工作大多将这个问题表示为离散的导航图&#x…

MySQL基础教程(一):连接数据库和使用表

这个专栏用来讲解 MySQL 数据的基本语法和用法。本教程的目的是方便查询 MySQL 的用法&#xff0c;因此对于原理的讲解会偏少一些&#xff0c;但特点就是会有很多实验操作图。 本专栏使用的源材料是《MySQL必知必会》这本书的源代码。 文章目录 1. 连接 MySQL 数据库2. 创建数…

【物流配送中心选址问题】基于改进粒子群算法

课题名称&#xff1a; 基于改进粒子群算法的物流配送中心选址问题 改进方向&#xff1a;动态惯性权重优化粒子群算法 代码获取方式&#xff1a; 模型描述&#xff1a; 待补充 Matlab仿真结果&#xff1a; 1. 模型优化后的仿真结果 2. 初始解对应的物流配送路径图 3. 粒子…

Tianrui Green Shield

Tianrui Green Shield&#xff0c;即天锐绿盾&#xff0c;是一款专注于企业数据防泄密的软件系统。以下是对天锐绿盾的详细介绍&#xff1a; 一、基本信息 产品名称&#xff1a;天锐绿盾&#xff08;又名绿盾信息安全管理软件&#xff09;公司官网&#xff1a;www.drhchina.co…

VMware中Ubuntu系统Docker正常运行但网络不通(已解决)

问题描述&#xff1a;在VMware中的Ubuntu系统下部署了Docker&#xff0c;当在docker容器中运行Eureka微服务时&#xff0c;发现Eureka启动正常&#xff0c;但无法通过网页访问该容器中Eureka。 解决办法如下&#xff1a; 1、创建桥接网络&#xff1a;test-net sudo docker n…

2024年最强网络安全学习路线,详细到直接上清华的教材!

关键词&#xff1a;网络安全入门、渗透测试学习、零基础学安全、网络安全学习路线 首先咱们聊聊&#xff0c;学习网络安全方向通常会有哪些问题前排提示&#xff1a;文末有CSDN官方认证Python入门资料包 &#xff01; 1、打基础时间太长 学基础花费很长时间&#xff0c;光语…

微信第三方开放平台接入本地消息事件接口报错问题java.security.InvalidKeyException: Illegal key size

先看报错&#xff1a; java.security.InvalidKeyException: Illegal key sizeat javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039)at javax.crypto.Cipher.implInit(Cipher.java:805)at javax.crypto.Cipher.chooseProvider(Cipher.java:864)at javax.crypto.Cipher.in…

Java基础(上)

Java的特性 简单易学&#xff08;语法简单&#xff0c;上手容易&#xff09;&#xff1b; 面向对象&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;&#xff1b; 平台无关性&#xff08; Java 虚拟机实现平台无关性&#xff09;&#xff1b; 支持多线程&…