【数据结构】希尔排序(缩小增量排序)

目录

一、基本思想

1.1 引入希尔排序的原因

1.2 基本思想

二、思路分析

三、gap分组问题

四、代码实现

4.1 代码一(升序)

4.2 代码二(升序)

五、易错提醒

六、时间复杂度分析

七、排序小tips


一、基本思想

1.1 引入希尔排序的原因

为什么要引入希尔排序呢?

因为直接插入排序的缺点就是怕逆序,如果待排的序列是逆序的情况,那么效率将直接下降,而希尔排序就是对直接插入排序的一个优化。

那什么是希尔排序呢?

1.2 基本思想

希尔排序法又称缩小增量法。希尔排序法的基本思想是:

将待排序的序列划分成若干个子序列(也就是若干组),分别进行插入排序,待整个序列中的记录基本有序时,再对全体记录进行一次直接插入排序。

通俗来讲,希尔排序分为两步:

  1. 预排序(目的:让数组接近有序)
  2. 直接插入排序

二、思路分析

我们清楚直接插入排序是如何实现的,那预排序是如何实现的呢?

接下来我们结合图来详细讲解一下希尔排序中预排序的过程:

这里以升序为例:

预排序完成之后,一组,二组,三组分别都是一组有序的序列,

虽然没有达成整个序列的有序,但相比之前,更加接近有序。

在此基础上,进行直接插入排序,会比之前更快,

之前的9需要移动n次,而现在的9只需要移动3次,因为每跳一次,步长为3,跳的更远了,所以移动的速度也就更快了。

所以说,预排序针对逆序情况特别凸显它的效率高效。

三、gap分组问题

预排序到底排几次比较合适,gap分为几组才是最恰当的呢?

我们知道:

gap越大,我们期望它可以跳的越快。大的数据就可以越快的跳到后面,小的数据也就可以越快的跳到前面。

当然,整个序列也就越不接近有序。

gap越小,它就跳的越慢,整个序列也就越接近有序。

当gap>1的时候,是预排序

当gap==1的时候,就是直接插入排序。

gap的取值方式有很多种,研究发现,gap=gap/3;是相对比较合理的,但是除以3并不能保证最后一次gap==1(也就是无法进行直接插入排序,因为希尔排序=预排序+直接插入排序)

所以,gap=gap/3+1;就可以保证最后一次gap一定等于1,也就是可以进行直接插入排序。

当然我们也可以选择gap=gap/2,但最好还是使用gap=gap/3+1。

四、代码实现

4.1 代码一(升序)

//一组一组执行
void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){//+1保证最后一次gap一定是1//gap>1 预排序//gap==1 直接插入排序gap = gap / 3 + 1;//完成一趟预排序for (int j = 0; j < gap; j++){//完成一组的排序for (int i = 0; i < n - gap; i += gap){int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}}
}

4.2 代码二(升序)

//多组并行走
void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){gap = gap / 3 + 1;//完成一趟的排序for (int i = 0; i < n - gap; i++){int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}
}

五、易错提醒

提醒一

代码一和代码二是两种执行次序,具体执行步骤如下所示:

代码一

代码二

代码一和代码二在效率执行上并没有任何区别,因为它们完成的是同一个过程。


提醒二

注意临界问题,for循环里i<n-gap的原因:

六、时间复杂度分析

希尔排序的平均时间复杂度是:O(N^1.3)

为什么呢?

我们可以进行一下简单的推导:

一共有gap组数据,gap=gap/3+1,这里假设忽略掉+1(目的是为了方便计算),变成gap=gap/3,

那么每组就有3个数据,因为每组数据个数=n/gap(n为数据总数)

例:下图n=12,共有12个数据,每组有3个数据,所以共分了4组,也就是gap=n/3=4.

这里千万不要混淆gap组的意思,根据图来进行理解

我们知道,一趟预排序的消耗次数=每组的比较次数*组数

所以,

第一趟预排序消耗的次数(最坏情况下):(1+2)*n/3=n   

(因为gap=gap/3=n/3,所以每组3个数据)

1表示:一组序列的第二个元素最坏比较多少次

2表示:一组序列的第三个元素最坏比较多少次

n/3表示:一共有多少组

第二趟预排序消耗的次数(最坏情况下):(1+2+3+......+8)*n/9=9*8/2*n/9=4n

(因为gap=gap/3=n/3/3=n/9,所以每组9个数据)

依次类推......

这里需要注意的是:

        当进行了第一趟最坏情况下的预排之后,第二趟不一定最坏了,因为第一趟预排序对第二趟预排有一定的影响。

        严格来说第二趟到不了最坏的情况,它应该比4n要小,那具体是多少,就很难算出来,这里涉及复变函数,概率等知识的运用。

所以说到最后一趟,也就是当gap==1时,就是直接插入排序

此时的序列已经非常接近有序了。

 所以,

最后一趟预排序消耗次数(正常情况下):n

这里可以用函数关系图来表示希尔排序比较次数和gap之间的关系:

从图中我们可以看出他们之间大致关系如上所示,经推算希尔排序的平均时间复杂度为:O(N^1.3)


这里我们也可以用另一种方式来求解时间复杂度。

可以计算一下走了多少趟预排序,也就是gap变化了几次,外层while循环走了多少次?

分析如下图所示:

所以研究希尔排序的最好时间复杂度是没有任何意义的。


提醒:

  1. 希尔排序的时间复杂度不好计算,因为gap取值方式的不同,会对排序效率有直接影响,这就导致了希尔排序的时间复杂度计算变得复杂,很难给出一个确切的复杂度,因此很多资料中希尔排序的时间复杂度都不固定。
  2. 我们上述分析的是按照Knuth提出的方式取值的,而Knuth进行了大量试验统计资料得出,当n很大时关键码平均比较次数和对象平均移动次数大约在 O(n^1.25)到 O(1.6n^1.25)范围内。

        故,我们直接按照O(N^1.3) 来计算即可。

七、排序小tips

我们在进行任何排序都要先处理好单趟的问题,然后再考虑整体,这样可以使我们写代码的思路更加清晰明了,也更容易写出正确高效的代码。

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

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

相关文章

【即时通讯】轮询方式实现

技术栈 LayUI、jQuery实现前端效果。django4.2、django-ninja实现后端接口。 代码仓 - 后端 代码仓 - 前端 实现功能 首次访问页面并发送消息时需要设置昵称发送内容为空时要提示用户不能发送空消息前端定时获取消息&#xff0c;然后展示在页面上。 效果展示 首次发送需要…

【老课推荐】基于LangChain和知识图谱的大模型医疗问答机器人项目

在当今数据驱动和人工智能主导的时代&#xff0c;大模型和知识图谱的结合是一个重要的研究和应用方向。大模型实战课程通过48课时&#xff0c;分为六个主要章节&#xff0c;涵盖了从基本概念到高级应用的多方面内容。学员将通过本课程学习如何使用LangChain和OpenAI进行开发&am…

windows10-VMware17-Ubuntu-22.04-海康2K摄像头兼容问题,求解(已解决)

文章目录 1.webrtc camera测试2.ffmpeg 测试3.Ubuntu 自带相机4.解决办法 环境&#xff1a;windows10系统下&#xff0c;VMware的Ubuntu-22.04系统 问题&#xff1a;摄像头出现兼容问题&#xff0c;本来是想开发测试的&#xff0c;Ubuntu方便些。买了海康2K的USB摄像头&#xf…

自动驾驶ADAS算法--使用MATLBA和UE4生成测试视频

原文参考&#xff1a;金书世界 环境搭建参考&#xff1a;用MATLAB2020b和虚拟引擎&#xff08;Unreal Engine&#xff09;联合仿真输出AVM全景测试视频----Matlab环境搭建 matlab参考&#xff1a; https://ww2.mathworks.cn/help/driving/ug/simulate-a-simple-driving-sce…

【Transformer】Positional Encoding

文章目录 为什么需要位置编码&#xff1f;预备知识三角函数求和公式旋转矩阵逆时针旋转顺时针旋转旋转矩阵的性质 原始Transformer中的位置编码论文中的介绍具体计算过程为什么是线性变换&#xff1f; 大模型常用的旋转位置编码RoPE基本原理最简实现形式Llama3中的代码实现 两种…

智汇云舟受邀参加2024第四届国产水科学数值模型开发创新与技术应用研讨会,并成为“科技智水产业联盟”创始成员

在数字化浪潮的推动下&#xff0c;智慧水利作为国家战略的重要组成部分&#xff0c;正迎来前所未有的发展机遇。8月27-29日&#xff0c;由浙江贵仁信息科技股份有限公司主办、浙江省水利学会协办的“2024第四届国产水科学数值模型开发创新与技术应用研讨会”在杭州白马湖建国饭…

ML19_GMM高斯混合模型详解

1. 中心极限定理 中心极限定理&#xff08;Central Limit Theorem, CLT&#xff09;是概率论中的一个重要定理&#xff0c;它描述了在一定条件下&#xff0c;独立同分布的随机变量序列的标准化和的分布趋向于正态分布的性质。这个定理在统计学中有着广泛的应用&#xff0c;尤其…

maven配置文件常用模板

注释很详细&#xff0c;直接上代码 项目结构 内容 父项目 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi…

context canceled 到底谁在作祟?

一、背景 在工作中&#xff0c;因报警治理标准提高&#xff0c;在报警治理的过程中&#xff0c;有一类context cancel报警渐渐凸显出来。 目前context cancel日志报警大致可以分为两类。 context deadline exceeded 耗时长有明确报错原因 context canceled 耗时短无明确报错…

Android13_SystemUI下拉框新增音量控制条

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 Android13_SystemUI下拉框新增音量控制条 一、必备知识二、源码分析对比1.brightness模块分析对比2.statusbar/phone 对应模块对比对比初始化类声明对比构造方法 三、源码修改…

OpenCV结构分析与形状描述符(11)椭圆拟合函数fitEllipse()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 围绕一组2D点拟合一个椭圆。 该函数计算出一个椭圆&#xff0c;该椭圆在最小二乘意义上最好地拟合一组2D点。它返回一个内切椭圆的旋转矩形。使…

树莓派3B串口通信

树莓派3B串口通信 文章目录 树莓派3B串口通信一、串口的基本认知1.1 关于电器标准和协议&#xff1a;RS232RS422RS485 1.2 关于串口的电平&#xff1a;UARTRS232电平TTL电平 1.3 串口通信引脚接线&#xff1a;1.4 串口的通信协议&#xff1a; 二、树莓派串口通信开发2.1 树莓派…

TensorRT-For-YOLO-Series项目:实现yolov10模型的python-tensorrt推理(对比int8与fp16推理差异)

项目地址&#xff1a;https://github.com/Linaom1214/TensorRT-For-YOLO-Series/tree/cuda-python 算法支持状态&#xff1a; 2024.6.16 Support YOLOv9, YOLOv10, changing the TensorRT version to 10.0 2023.8.15 Support cuda-python 2023.5.12 Update 2023.1.7 support YO…

观趋势 谋发展 2024 SSHT上海智能家居展有哪些创新呈现?

引言&#xff1a;大数跨境发布的《2024全球智能家居市场洞察报告》显示&#xff0c;智能家居市场正迎来快速增长&#xff0c;预计从2024年的1215.9亿美元增长至2032年的6332.0亿美元&#xff0c;复合年增长率为22.9%。 近年来&#xff0c;随着物联网、AI等底层技术的飞速进步&…

kubernetes微服务之ingress-nginx

目录 1 ingress-nginx 介绍 2 Ingress-nginx 的工作原理 3 使用 Ingress-nginx 的步骤 4 部署 ingress &#xff1a; 4.1 开启ipvs 模式 4.2 下载部署文件 4.3 上传镜像到harbor 4.4 修改文件中镜像地址,与harbor仓库路径保持一致 4.5 检查是否running 4.6 将ingress的命名…

轻松上手,高效产出:音频剪辑工具年度精选

不知道你有没有拍vlog记录生活的习惯&#xff0c;有时候视频里穿插进自己的声音能让视频更加丰富贴上自己的标签。这次我们一起探讨当下有哪些好用的在线音频剪辑工具。 1.FOXIT音频剪辑 链接直达>>https://www.foxitsoftware.cn/audio-clip/ 这个工具是一款专业的音…

Java 数据类型详解:基本数据类型与引用数据类型

在 Java 编程语言中&#xff0c;数据类型主要分为两大类&#xff1a;基本数据类型和引用数据类型。理解这两种类型的区别、使用场景及其转换方式是学习 Java 的基础。本文将深入探讨这两类数据类型的特点&#xff0c;并展示自动类型转换、强制类型转换以及自动拆箱和封箱的使用…

虚拟现实辅助工程技术助力多学科协同评估

在当今高速发展的经济环境中&#xff0c;制造业面临着多重挑战&#xff0c;包括提高产品性能、压缩设计周期、实现轻量化设计和降低成本。为了有效应对这些挑战&#xff0c;多学科协同评估成为缩短研发周期和提升研制质量的关键手段。 传统的多学科评估面临着数据孤立与融合困难…

《‌黑神话:‌悟空》‌游戏攻略‌

时光荏苒&#xff0c;岁月如梭&#xff0c;不知不觉已经来到了2024年的9月份了。 ‌突然想写一篇关于《‌黑神话&#xff1a;‌悟空》‌的游戏攻略‌。 在《‌黑神话&#xff1a;‌悟空》‌这款以中国古代名著《‌西游记》‌为背景的动作角色扮演游戏中&#xff0c;‌玩家将扮…

LeetCode 热题 100 回顾9

干货分享&#xff0c;感谢您的阅读&#xff01;原文见&#xff1a;LeetCode 热题 100 回顾_力code热题100-CSDN博客 一、哈希部分 1.两数之和 &#xff08;简单&#xff09; 题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标…