【探索数据结构与算法】希尔排序原理、实现与分析(图文详解)

目录

一、 引言

二、算法思想 

三、算法步骤 

 四、代码实现 

五、复杂度 


💓 博客主页:C-SDN花园GGbond

⏩ 文章专栏:探索数据结构与算法

一、 引言

希尔排序(Shell Sort)是插入排序的一种更高效的改进版本,也称为缩小增量排序。

希尔排序的直接灵感来源于插入排序,但它在插入排序的基础上进行了显著的改进,旨在提高排序效率,特别是针对大规模数据集

二、算法思想 

将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次标准的直接插入排序。

这里的“基本有序”是指:待排序的数组元素值满足某个增量序列的“局部有序”,即对于某个变量gap,序列中所有距离为gap的元素之间是有序的。随着变量gap的逐渐减小,当gap减小到1时,整个序列恰好被“基本有序”,此时再对全体元素进行一次直接插入排序即可

三、算法步骤 

  1. 选取一个gap对数据进行分组,每间隔gap个元素分为一组,一共gap组。
  2. 以gap为基准单位,对其进行插入排序。
  3. 依次缩小gap的范围,直至gap为1,相当于进行一次正常的插入排序。

  

 动图演示 

1.外循环进行多轮预排序 

选择一个变量序列gap:

这个序列是逐渐减小的,gap的值较大时,数据可以更快的前后变动,但不容易"基本有序";gap较小时数据前后变动较慢,但更接近"基本有序"。  通常可以选取gap = n/3, gap = gap/3, ...,直到gap= 1。

.递减变量gap并重复上述分组排序过程:

每完成一轮按变量gap的分组排序后,将变量gap减小,然后重复分组排序过程,直到变量gap为1,此时整个数组恰好被分成一组,进行最后一次直接插入排序。

注意,如果直接每次都/3,可能面临的情况就是最后一组gap的值跳过了1,比如n=8时,gap第一次等于2,第二次等于0,解决方法也很简单,gap每次不是/3,而是gap=gap/3+1,就可以让gap最后一次一定会减小到1

2.第二层循环,每一轮预排序中进行分组

按gap进行分组:根据当前的变量gap,将待排序的数组元素下标按gap分组,总共可以分成gap组。比如gap为3时,每一组元素的首元素分别是0,1,2

每一组的数据有n/gap个,下标为0,gap, 2gap, 3gap,...的元素分为一组;下标为1,gap+1,2gap+1,3gap+1……的元素分为一组……

3.第三层循环,分组之后,控制组里数据执行插入排序 

这一层循环一个需要注意的细节就是预防数组的越界:。每次选取的要插入的数据下标是end+gap,那么这个下标不能超过n-gap。比如数组有10个元素,gap为3,第一组数据最后一个数据的下标是9,要保证这一组数据访问到下标9之后,不再向后访问,因为下一次访问end为9,要插入的数据,9+gap的位置已经没有数据了。

4.第四层循环,实现插入排序的过程
每个数据向前扫描和移动,找到合适的位置后插入,直接在插入排序代码的基础上稍加修改即可 

 四、代码实现 

//希尔排序分组进行
void ShellSort1(int* a,int len)
{int gap = len;while (gap > 1)//多组预排序,最后一组gap==1为直接插入排序{gap = gap / 3 + 1;for (int i = 0; i < gap; i++)//控制分组的组数:gap组{for (int j=i; j < len - gap; j += gap)//控制每组的插入元素个数:n/gap个{int end = j;int tmp = a[end + gap];while (end >= 0){if (a[end] > tmp)//比较和移动元素{a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;//满足大小关系后插入到指定位置}}}}
//希尔排序同时进行
void ShellSort2(int* a, int len){int gap = len;while (gap > 1){gap = gap / 3 + 1;for (int i = 0; i < len-gap; i++){int end = i;int tmp = a[end + gap];while (end >= 0){if (a[end] > tmp){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}
}

希尔排序不分组同时进行

将第二层第三层循环合为一层循环,
以前是四层循环时,我们是将分组作为一层循环,每组里的数据插入作为一层循环
将两层循环合为一层之后,不是一组一组进行预排序,而是将数据逐个的,与它对应的组里的数据进行预排序,互不影响
优化之后代码更加简洁,但效率没有提升  

五、复杂度 

  • 时间复杂度:希尔排序的时间复杂度一般较为难计算,通过大量测验一般认为其时间复杂为O(N1.3 )。
  • 空间复杂度:没有开辟额外的空间大小,所以空间复杂度为O(1)。
  • 希尔排序是原地排序算法,它只需要一个额外的空间来存储临时变量(用于数据交换),因此其空间复杂度为O(1)。这意味着希尔排序在排序过程中不会占用额外的存储空间,这对于内存资源有限的环境非常有利。

 稳定性:不稳定的

希尔排序是不稳定的排序算法。在排序过程中,由于存在跳跃式的比较和移动,相同元素的相对位置可能会发生变化。因此,在需要保持元素原始顺序的场景中,希尔排序可能不是最佳选择。

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

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

相关文章

oracle 使用 PL/SQL Developer创建表并插入单条、多条数据

第一步&#xff1a;使用工具创建表&#xff08;前提是库已经创建好了&#xff09;&#xff1a;在当前用户下找到Tables 然后点击并右键&#xff0c;点击新建 写上表名&#xff0c;写上表名的注释 第二步添加字段&#xff1a;点击列&#xff0c;然后分别写上你自己需要的字段及名…

LDR6020,单C口OTG,充放一体新潮流!

PD&#xff08;Power Delivery&#xff09;芯片实现单Type-C接口输入和输出OTG&#xff08;On-The-Go&#xff09;功能&#xff0c;主要是通过支持USB Power Delivery规范和OTG功能的特定硬件和软件设计来实现的。以下是对这一过程的具体解释&#xff1a; 一、PD芯片基础功能 …

OpenCV_图像像素读写操作

本文详细介绍了如何在C项目中使用OpenCV进行图像像素的读写操作&#xff0c;包括使用头文件声明Pixel类&#xff0c;通过遍历和指针方式处理灰度图和彩色图&#xff0c;以及在主函数中调用这些操作。 数组遍历的方式进行图像像素读写 void QuickDemo::pixelVisit_Demo(Mat&am…

【Android安全】Ubuntu 16.04安装GDB和GEF

1. 安装GDB sudo apt install gdb-multiarch 2. 安装GEF(GDB Enhanced Features) 官网地址&#xff1a;https://github.com/hugsy/gef 2.1 安装2021.10版本 但是在Ubuntu 16.04上&#xff0c;bash -c "$(curl -fsSL https://gef.blah.cat/sh)"等命令不好使&…

文字loading加载

效果 1. 导入库 import sys from PyQt5.QtCore import QTimer, Qt, QThread, pyqtSignal from PyQt5.QtGui import QPainter, QFont, QColor, QBrush from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QProgressBar, QLabel 代码首先导入了P…

django-admin自定义功能按钮样式

位置在原来的django-admin 栏中的上方【会因为屏幕大小而变换位置】 <!-- 这里是不会替换掉旧的 添加按钮 &#xff0c;而是添加多一个按钮【点击Crawl Data】--> <!-- /home/luichun/lc/Pyfile/Pywebback/app/paqu/templates/admin/yourmodel_changelist.html -->…

深度揭秘:日志打印的艺术与实战技巧,让你的代码会说话!

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;Linux从入门到进阶 欢迎大家点赞收藏评论&#x1f60a; 目录 &#x1f341;日志&#x1f342;日志分模块实现讲解&#x1f343;日志等级的实现&#x1f965;日志时间*时间的获取* &#x1f308;文…

web基础之文件上传

1.下载安装 下载地址 链接&#xff1a;百度网盘-链接不存在 提取码&#xff1a;jhks 安装 直接把他放在phpstudy的WWW目录中。&#xff08;phpstudy的下载安装&#xff0c;可以自行百度一下&#xff09; 打开 访问地址&#xff1a;127.0.0.1/upload-labs 问题 这里可能…

开源PDF工具 Apache PDFBox 认识及使用(知识点+案例)

文章目录 一、认识PDFBox一、pandas是什么&#xff1f;二、导入依赖三、基础功能demo1&#xff1a;读取pdf所有内容demo2&#xff1a;读取所有页内容&#xff08;分页&#xff09;demo3&#xff1a;添加页眉、页脚demo4&#xff1a;添加居中45文字水印demo5&#xff1a;添加图片…

数据结构——栈和队列(队列的定义、顺序队列以及链式队列的基本操作)

目录 队列&#xff08;queue&#xff09;的定义 顺序队——队列的顺序表示和实现 顺序队列&#xff08;循环队列&#xff09;的类型定义 顺序队列上溢问题的解决方法 ​编辑 循环队列的基本操作 队列的基本操作——队列的初始化 队列的基本操作——求队列的长度 队列的…

Element UI入门笔记(个人向)

Element UI入门笔记 将页面分割为一级菜单、二级菜单、导航栏三个部分&#xff1b;使用npm下载安装&#xff0c;使用语句npm i element-ui -s; 布局组件 el-form 用于创建和管理表单&#xff1b;从属性上看&#xff1a; :model&#xff1a;用于双向数据绑定&#xff0c;将表单…

Windows下SDL2创建最简单的一个窗口

先看运行效果 再上代码&#xff1a; #include <stdio.h> #include "SDL.h"int main(int argc, char* argv[]) {// 初始化SDL视频子系统if (SDL_Init(SDL_INIT_VIDEO) -1){printf("Error: %s\n", SDL_GetError());return -1;} // 创建一个窗口SDL_…

『功能项目』战士职业平A怪物掉血【44】

我们打开上一篇43事件中心的项目&#xff0c; 本章要做的事情是给主角增加一个xxxCtrl.cs脚本&#xff0c;再创建一个xxxOpt.cs调用xxxCtrl.cs机制层利用事件中心再写一个主角战士平A对怪物的伤害 首先创建脚本&#xff1a;PlayerCtrl.cs using UnityEngine; public class Pla…

JavaScript 笔记汇总

JavaScript 笔记汇总 引入方式 内部方式 通过 script 标签包裹 JavaScript 代码。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>JavaScript 基础 - 引入方式</title> </head> <…

校园社团|基于springBoot的校园社团信息管理系统设计与实现(附项目源码+论文+数据库)

私信或留言即免费送开题报告和任务书&#xff08;可指定任意题目&#xff09; 目录 一、摘要 二、相关技术 三、系统设计 四、数据库设计 五、核心代码 六、论文参考 七、源码获取 一、摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信…

顺序表(c语言实现)

顺序表是一种数据结构&#xff0c;它在计算机内存中以连续的存储位置来存储数据元素。 一、特点 1. 随机访问&#xff1a;可以在常数时间内访问特定位置的元素&#xff0c;例如&#xff0c;通过下标可以快速找到对应元素。 2. 存储密度高&#xff1a;不需要额外的指针来链接…

【运维监控】Prometheus+grafana+kafka_exporter监控kafka运行情况

运维监控系列文章入口&#xff1a;【运维监控】系列文章汇总索引 文章目录 一、prometheus二、grafana三、部署kafka_exporter1、下载2、解压3、配置4、启动5、验证 四、prometheus集成grafana监控kafka1、修改prometheus配置2、导入grafana模板3、验证 本示例通过kafka_export…

从0书写一个softmax分类 李沐pytorch实战

输出维度 在softmax 分类中 我们输出与类别一样多。 数据集有10个类别&#xff0c;所以网络输出维度为10。 初始化权重和偏置 torch.norma 生成一个均值为 0&#xff0c;标准差为0.01,一个形状为size(num_inputs, num_outputs)的张量偏置生成一个num_outputs 10 的一维张量&a…

【计网】数据链路层:概述之位置|地位|链路|数据链路|帧

✨ Blog’s 主页: 白乐天_ξ( ✿&#xff1e;◡❛) &#x1f308; 个人Motto&#xff1a;他强任他强&#xff0c;清风拂山岗&#xff01; &#x1f4ab; 欢迎来到我的学习笔记&#xff01; ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ 1. 在OSI体系结构中的位置 1. 位置&#xff1a;数…

ICMP

目录 1. 帧格式2. ICMPv4消息类型(Type = 0,Code = 0)回送应答 /(Type = 8,Code = 0)回送请求(Type = 3)目标不可达(Type = 5)重定向(Type = 11)ICMP超时(Type = 12)参数3. ICMPv6消息类型回见TCP/IP 对ICMP协议作介绍 ICMP(Internet Control Message Protocol…