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

在这里插入图片描述

👦个人主页:Weraphael
✍🏻作者简介:目前正在学习c++和算法
✈️专栏:数据结构
🐋 希望大家多多支持,咱一起进步!😁
如果文章有啥瑕疵
希望大佬指点一二
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注😍


目录

  • 一、希尔排序的由来
  • 二、算法思路
  • 三、预排序代码实现
  • 四、如何选择gap
  • 五、代码实现(完整版)
  • 六、性能分析

一、希尔排序的由来

  • 从直接插入排序中,我们总结了:(假定要求升序)当原数组是逆序的时候,时间复杂度为O(N2),效率极低。博客地址:点击跳转
  • 当原数组是接近升序或者已经是有序的,那么时间复杂度就是O(N),此时效率最高。

因此,又一位名叫希尔的大佬发现,如果一开始就让数组内的元素接近有序的话,那插入排序的效率不就大大提升了吗?所以,希尔排序是插入排序的优化

二、算法思路

  1. 预排序首先让序列中的元素接近有序

那么如何进行预排序呢?(重点)

其运用了 分组插排 的思想:定义一个变量gap,间隔为gap分为一组进行插入排序

  1. 最后再对数组进行插入排序即可

【画图演示】

在这里插入图片描述

通过以上图片,我们还可以总结一个规律:gap为几,就代表预排序有几组

接下来我们简单实现预排序的代码。

三、预排序代码实现

void ShellSort(int a[], int n)
{
    // 假设gap为3
    int gap = 3;
    // 1. gap是几,就代表有几组
    for (int i = 0; i < gap; i++)
    {
        // 2. 间隔为gap为一组进行插入排序
        for (int j = i; j < n - gap; j += gap)
        {
        	// 下面基本都是插入排序的代码(类似)
            int end = j;
            int temp = a[j + gap];
            while (end >= 0)
            {
                if (temp < a[end])
                {
                    a[end + gap] = a[end];
                    end -= gap;
                }
                else
                {
                    a[end + gap] = temp;
                }
            }
            a[end + gap] = temp;
        }
    }
}

那么最后就要对整体进行插入排序,这样就能完美实现希尔排序了。但是我们难道还要重新再其后再手搓一个插入排序吗?理论上是可以的,但是没必要。注意看:当间隔gap1时,不就是插入排序了吗?因此,普通插入排序和gap是有关系的。那么应该如何选择gap呢?

四、如何选择gap

gap越大,跳的越快,越不接近有序;gap越小,跳的越慢,越接近有序。

可以为大家验证一下:

  • gap = 3

在这里插入图片描述

是不是越接近有序!

  • gap = 5

在这里插入图片描述

虽然也接近有序,但是没有比gap = 3更接近有序!

那么gap到底取多少合适呢?

解答:gap应该要不断在变化。为什么呢?开头的结论:gap越大,跳的越快,越不接近有序;gap越小,跳的越慢,越接近有序。如果gap是固定大小,给大了越不接近有序,给小了接近有序,但是跳的慢。因此,预排序的为了让更大的数更快的跳到后面,越小数越快跳到前面。这就是为什么gap应该要不断的变化。

  • 最初希尔大佬提出取gap /= 2,为什么呢?因为一个数不断/2,最后的结果一定为1,那么在上面我们说过,当gap = 1,就可以满足整体的插入排序,就不需要再手搓普通插入排序了。

  • 后来Knuth提出取gap = gap / 3 + 1+1为了保证最后gap一定为1,还有人提出取奇数好,也有人提出gap互质好。但无论哪一种主张都没有得到证明。其实都是ok的

五、代码实现(完整版)

void ShellSort(int a[], int n)
{
	// 3. 如何取gap
    // gap最大可以取到整个数组的长度n
    int gap = n;
    while (gap > 1)
    {
        // gap = gap / 3 + 1; // 这也是okk的
        gap /= 2;
        //  1. gap是几,就代表有几组
        for (int i = 0; i < gap; i++)
        {
            // 2. 间隔为gap为一组进行插入排序
            for (int j = i; j < n - gap; j += gap)
            {
                int end = j;
                int temp = a[j + gap];
                while (end >= 0)
                {
                    if (temp < a[end])
                    {
                        a[end + gap] = a[end];
                        end -= gap;
                    }
                    else
                    {
                        break;
                    }
                }
                a[end + gap] = temp;
            }
        }
    }
}

【结果展示】

在这里插入图片描述

六、性能分析

  • 时间复杂度

希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算。Knuth大佬进行了大量的试验统计,计算出希尔排序的时间复杂度大约为O(N^1.3)

但是我们可以用代码进行性能测试的对比

在这里插入图片描述

如图,当数据个数是10w时,插入排序和希尔排序时间效率如下所示

在这里插入图片描述

由此看出,希尔排序还是非常的牛逼的~

  • 有人想:希尔排序在预排序的时候不是运用到很多的插入排序,为什么其效率还是比插入排序高?

原因是:其实gap的取值决定数组内的元素是否接近有序,gap越大,排的也越快,但越不接近有序;gap越小,排的也就越慢,但越接近有序。所以一开始gap的值可以设为数组元素个数(gap一定不可能超过数组元素个数),每次进行/2,不断缩小gap,其实最后发现,希尔排序的插入排序的次数其实是小于直接排序的插入次数的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构初阶】链表OJ

链表OJ 题目一&#xff1a;移除链表元素题目二&#xff1a;反转链表题目三&#xff1a;链表的中间节点题目四&#xff1a;链表中倒数第k个结点题目五&#xff1a;合并两个有序链表题目六&#xff1a;链表分割题目七&#xff1a;链表的回文结构题目八&#xff1a;相交链表题目九…

JavaScript概述

一、JavaScript简介&#xff1a; JavaScript是互联网上流行的脚本语言&#xff0c;可用于HTML和web&#xff0c;可广泛应用于服务器、PC、笔记本、平板电脑和智能手机等设备。 JavaScript是一种轻量级的编程语言&#xff0c;可插入HTML页面的编程代码&#xff0c;插入HTML页面后…

联盟 | Quick Creator X HelpLook ,AI助力打造出海企业内容营销

随着人工智能的快速发展&#xff0c;各行各业也加快了人工智能工具的探索&#xff0c;积极将AI融入到行业发展中&#xff0c;出海外贸也不例外。AI渐渐地融入到外贸的各个环节&#xff0c;为企业出海提速增效。 为此&#xff0c;「 Quick Creator 」与 「 HelpLook 」达成战略合…

mask-rcnn原理与实战

一、Mask R-CNN是什么&#xff0c;可以做哪些任务&#xff1f; Mask R-CNN是一个实例分割&#xff08;Instance segmentation&#xff09;算法&#xff0c;可以用来做“目标检测”、“目标实例分割”、“目标关键点检测”。 1. 实例分割&#xff08;Instance segmentation&am…

Python爬虫的七个常用技巧总结,这些你一定得知道!

文章目录 前言1、基本抓取网页2、使用代理IP3、Cookies处理4、伪装成浏览器5、验证码的处理6、gzip压缩7、多线程并发抓取关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战…

前端element的el-tooltip鼠标经过显示文字,没有文字显示空黑框问题

场景&#xff1a; 有时候在使用element的el-tooltip时会使用三元表达式&#xff0c;满足某个条件后才显示提示文字&#xff0c;否则不展示文字&#xff0c;但是却出现在在没有文字时展示了黑框&#xff0c;如下图&#xff1a; 解决方案&#xff1a; 加一个disabled便可&#…

手机维修店服务预约小程序的效果怎样

手机维修店在每个城市的商业街或商场里都很常见&#xff0c;目前人手一个或多个手机&#xff0c;虽然手机质量有了提升&#xff0c;但各种毛病依然无法避免&#xff0c;因此手机维修店虽然不是人挤人&#xff0c;但整体生意还可以&#xff0c;各种服务也愈加完善。 而市场接受…

人力物力和时间资源有限?守住1个原则,精准覆盖所有兼容性测试!

随着 APP 应用范围越来越广&#xff0c;用户群体越来越大&#xff0c;终端设备的型号也越来越多&#xff0c;移动终端碎片化加剧&#xff0c;使得 APP 兼容性测试成为测试质量保障必须要考虑的环节。 APP 兼容性测试通常会考虑&#xff1a;操作系统、厂家 ROM、屏幕分辨率、网…

掌握Python中的控制流语句:break, continue, quit的应用技巧详解

引言 在Python编程中&#xff0c;控制流语句是非常重要的一部分&#xff0c;它们可以帮助我们控制程序的执行流程。其中&#xff0c;break、continue和quit是常用的控制流语句&#xff0c;它们可以在循环中起到关键作用。本文将详细介绍这些控制流语句的应用技巧&#xff0c;帮…

7天入门python系列之爬取热门小说项目实战,互联网的东西怎么算白嫖呢

第七天 Python项目实操 编者打算开一个python 初学主题的系列文章&#xff0c;用于指导想要学习python的同学。关于文章有任何疑问都可以私信作者。对于初学者想在7天内入门Python&#xff0c;这是一个紧凑的学习计划。但并不是不可完成的。 学到第7天说明你已经对python有了一…

Playwright UI 自动化测试实战

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

VSCode配置MingW编译调试环境

1.MingW简介 MinGW&#xff0c;即 Minimalist GNU For Windows。它是一些头文件和端口库的集合&#xff0c;该集合允许人们在没有第三方动态链接库的情况下使用 GCC&#xff08;GNU Compiler C&#xff09;产生 Windows32 程序。 实际上 MinGW 并不是一个 C/C 编译器&#xf…

亚马逊产品召回后如何重新发布商品?儿童睡衣,婴儿沐浴座椅,不锈钢儿童水杯被召回

近日&#xff0c;又有一款亚马逊热销超34w的产品出现安全问题。据外媒报道&#xff0c;7月20日&#xff0c;CPSC发现一款产品名为CUPKIN双层不锈钢儿童水杯存在铅中毒的风险&#xff0c;该水杯的铅含量超过联邦铅含量禁令。 CPSC在召回公告中指出&#xff0c;因为铅极容易被6岁…

南湖HIT论坛|《医疗数据安全风险分析及防范实践(2023)》正式发布

11月11日&#xff0c;2023年南湖HIT论坛在浙江嘉兴隆重举行。作为颇受HIT从业者关注的年度盛会——本届论坛以“数据驱动医院运营管理”为主题&#xff0c;全国各地医疗机构信息主管和骨干围绕“数据驱动运营管理、运营数据中心建设、数据治理和数据安全”等话题展开深入研讨。…

Python自动化测试:web自动化测试——Selenium框架

web自动化测试1 Selenium介绍web自动化实现原理环境准备1&#xff09;Seleniumpython环境搭建安装步骤环境变量的配置 2&#xff09;浏览器驱动驱动下载驱动环境配置 3&#xff09;版本检查4&#xff09;其他异常情况排查版本不一致未激活卸载、降低/升级setuptools版本 web自动…

什么是CSV文件,以及如何打开CSV文件格式

​CSV代表Comma Separated Values。CSV文件是一种纯文本文件&#xff0c;用于存储表格和电子表格信息。内容通常是由文本、数字或日期组成的表格。使用将数据存储在表中的程序可以轻松导入和导出CSV文件。 CSV文件格式 通常CSV文件的第一行包含表格列标签。后面的每一行表示表…

【软考篇】中级软件设计师 第三部分(一)

中级软件设计师 第三部分&#xff08;一&#xff09; 十七. I/O管理软件十八. 输入/输出技术十九. 总线系统二十. 磁盘管理20.1 移臂调度算法20.2 缓冲区 二十一. 操作系统二十二. 数据库22.1 三级模式-两级映射22.2 数据库设计22.3 规范化理论22.4 范式判断22.5 模式分解 二十…

单链表按位查找 按值查找与 求表长

按位查找 #define NULL 0typedef struct LNode {int data;struct LNode *next; }LNode,*LinkList;//按位查找&#xff0c;返回第i个元素&#xff08;带头结点&#xff09; LNode* GetElem(LinkList L,int i){if(i<0)return NULL;LNode *p L;int j 0;while (p!NULL &&a…

使用 MATLAB HDL Coder 和 FPGA 快速实现自动白平衡(AWB)

使用 MATLAB HDL Coder 和 FPGA 快速实现自动白平衡&#xff08;AWB&#xff09; 在此项目中&#xff0c;我们将使用 MATLAB Simulink 和 HDL 编码器创建自定义 IP -- AWB。 MATLAB 设计 自动白平衡模块的设计是使用 HDL Coder 在 MATLAB 和 Simulink 中创建的。HDL Coder能够生…

免费开源客服机器人tiledesk 实现一个查询天气机器人

第一步,槽位收集: 第二步:天气api接口调用: 效果展示: