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

在这里插入图片描述

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


目录

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

一、希尔排序的由来

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

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

二、算法思路

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

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

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

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

【画图演示】

在这里插入图片描述

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

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

三、预排序代码实现

void ShellSort(int a[], int n)
{// 假设gap为3int 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最大可以取到整个数组的长度nint 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,其实最后发现,希尔排序的插入排序的次数其实是小于直接排序的插入次数的。

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

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

相关文章

java springboot在当前测试类中添加临时属性 不影响application和其他范围

目前 我们的属性基本都写在 application.yml 里面了 但是 如果 我们只是想做一下临时变量的测试 有没有办法实现呢&#xff1f; 显然是有的 这里 我们还是先在application.yml中去写一个 test属性 下面加个prop 然后 我们尝试在测试类中 获取一下这个属性 直接用 Value 读取…

C语言——求1/1-1/2+1/3-......+1/99-1/100的值

#include<stdio.h> int main() {int i 1;double sum 0;int flage 1;for(i 1;i < 100; i){sumflage*1.0/i;flage -flage; //正负号}printf("%lf\n",sum);return 0; }

场景图形管理-多视图多窗口渲染示例(4)

多视图多窗口渲染示例的代码如程序清单8-6所示 // 多视图多窗口渲染示例 void compositeViewer_8_6(const string &strDataFolder) {// 创建一个CompositeViewer对象osg::ref_ptr<osgViewer::CompositeViewer> viewer new osgViewer::CompositeViewer();// 创建两个…

Outlook关闭过去事件的提醒

Outlook关闭过去事件的提醒 故障现象 最近Outlook中推出的新功能让我们可以选择自动关闭过去事件的提醒。 目前这个功能暂时只向当月通道的Office 365 订阅者发布。 这些用户升级到1810版本后&#xff0c;可以在不想收到已发生事件提醒的时候通过下面的步骤自动忽略过去事件…

day22_mysql

今日内容 零、 复习昨日 一、MySQL 一、约束 1.1 约束 是什么? 约束,即限制,就是通过设置约束,可以限制对数据表数据的插入,删除,更新 怎么做? 约束设置的语法,大部分是 create table 表名( 字段 数据类型(长度) 约束, 字段 数据类型(长度) 约束 );1.1 数据类型 其实数据类型…

在Spring Boot中使用进程内缓存和Cache注解

在Spring Boot中使用内缓存的时候需要预先知道什么是内缓存&#xff0c;使用内缓存的好处。 什么是内缓存 内缓存&#xff08;也称为进程内缓存或本地缓存&#xff09;是指将数据存储在应用程序的内存中&#xff0c;以便在需要时快速访问和检索数据&#xff0c;而无需每次都从…

Jmeter控制RPS

一、前言 ​ RPS (Request Per Second)一般用来衡量服务端的吞吐量&#xff0c;相比于并发模式&#xff0c;更适合用来摸底服务端的性能。我们可以通过使用 JMeter 的常数吞吐量定时器来限制每个线程的RPS。对于RPS&#xff0c;我们可以把他理解为我们的TPS&#xff0c;我们就不…

解决Github上的README无法显示图片

首先感谢博主的思路&#xff1a;思路 最近写了点东西提交到git 发现本地能查看md里的图片用的相对路径&#xff0c;提交到github就看不见&#xff0c;并且发现不只是我自己的仓库看不见&#xff0c;其他人的我也看不见。那就有问题了 解决&#xff1a;正常使用相对路径&…

使用Tauri开发桌面应用

本文是对视频 Tauri入门教程[1]的学习与记录 Tauri官网[2] 对 node版本有要求 创建项目及目录介绍: 项目的目录结构如下 可以安装推荐的插件 执行npm run tauri build出错,根据 https://github.com/tauri-apps/tauri/issues/7430 执行 yarn add -D tauri-apps/cli && y…

js的File对象,Blob和file相互转换

示例 <!DOCTYPE html> <html><head><meta charset"utf-8" /><meta name"viewport" content"widthdevice-width, initial-scale1" /><title>js的File对象&#xff0c;Blob和file相互转换</title><…

Android BitmapFactory.decodeResource读取原始图片装载成原始宽高Bitmap,Kotlin

Android BitmapFactory.decodeResource读取原始图片装载成原始宽高Bitmap&#xff0c;Kotlin fun getOriginalBitmap(resId: Int): Bitmap {val options BitmapFactory.Options()options.inJustDecodeBounds true //只解析原始图片的宽高&#xff0c;不decode原始文件装载到内…

t-product的matlab实现

t-product是一个比较好的概念&#xff0c;相对应于矩阵中的乘法。 定义如下 这里的 circ(A),MatVec(b) 的定义分别如下 这么定义的原因是为了映射到FFT域里面去&#xff0c;简化计算。 上面的一段摘录说明&#xff1a;直接按照定义来计算&#xff0c;会耗费大量的计算资源。因…

ATFX汇市:英国通胀率大降两个百分点,GBPUSD止步近两月高点

ATFX汇市&#xff1a;据英国国家统计局数据&#xff0c;英国10月CPI年率最新值4.6%&#xff0c;远低于前值6.7%&#xff0c;低于预期值4.8%&#xff0c;英国通胀率大降温&#xff0c;降幅高达2.1个百分点&#xff0c;远远超出市场预期。4.6%的通胀率是2021年10月以来最低值。主…

Go常见数据结构的实现原理——map

&#xff08;一&#xff09;基础操作 版本&#xff1a;Go SDK 1.20.6 1、初始化 map分别支持字面量初始化和内置函数make()初始化。 字面量初始化&#xff1a; m : map[string] int {"apple": 2,"banana": 3,}使用内置函数make()初始化&#xff1a; m …

Java 简单实现一个 TCP 回显服务器

文章目录 TCP 服务端TCP 客户端实现效果TCP 服务端(实现字典功能)总结 TCP 服务端 package network;import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Soc…

基于springboot的医护人员排班系统 全套代码 全套文档

基于springboot的医护人员排班系统,springboot vue mysql (毕业论文10411字以上,共27页,程序代码,MySQL数据库) 代码下载链接&#xff1a;https://pan.baidu.com/s/177HdCGtTvqiHP4O7qWAgxA?pwd0jlf 提取码&#xff1a;0jlf 【运行环境】 IDEA, JDK1.8, Mysql, Node, Vue …

HDP集群Kafka开启SASLPLAINTEXT安全认证

hdp页面修改kafka配置 java代码连接kafka增加对应的认证信息 props.put("security.protocol","SASL_PLAINTEXT");props.put("sasl.mechanism","PLAIN");props.put("sasl.jaas.config","org.apache.kafka.common.securi…

【华为HCIP | 华为数通工程师】ISIS 高频题(1)

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

Spring Boot 日志

日志概述 ⽇志对我们来说并不陌⽣&#xff0c;我们经常需要通过打印⽇志来发现和定位问题,或者根据⽇志来分析程序的运⾏过程.在Spring的学习中, 也经常需要根据控制台的⽇志来分析和定位问题. 打印日志 一&#xff1a;在程序中得到⽇志对象. 通过⽇志⼯⼚ LoggerFactory 获取…