【数据结构初阶】希尔排序

鼠鼠最近学习了希尔排序,做个笔记!

希尔排序也是插入排序的一种捏!本篇博客也是用排升序来举例捏!

希尔排序是基于直接插入排序的,是由大佬D.L.Shell提出的。

目录

1.希尔排序

1.1.预排序

1.2.直接插入排序

2.希尔排序的时间复杂度

3.希尔排序和直接插入排序的性能比较


1.希尔排序

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个 组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。如果不好懂没关系,继续看下面讲解:

鼠鼠上一篇博客介绍了直接插入排序应用时待排序的数组越接近有序,直接插入排序算法的时间效率越高。基于这个,D.L.Shell将希尔排序分为预排序和直接插入排序!

1.1.预排序

对待需排序的乱序数组,D.LShell不直接使用直接插入排序。他先搞一搞预排序。

预排序:

首先需排序的乱序数组分成gap组(若干组)。举个栗子吧:

让所有距离为gap的数分为一组,如图举例分为了gap=3组:蓝色组、红色组和绿色组。 

然后分别将蓝色组、红色组和绿色组的数据进行直接插入排序,这样每组数据排列都有序了,如图:

预排序其实大有作用,它能让待排序的乱序数组中大的数据尽量往后靠,让小的数据尽量往前靠,这样的话待排序的乱序数组就更接近有序。

那么我们来看看代码的推理过程:

1.我们先搞定蓝色组的直接插入排序的“单趟”:

				int end ;int tmp = a[end + gap];for (end; end >= 0; end -= gap){if (tmp < a[end]){a[end + gap] = a[end];}else{break;}}a[end + gap] = tmp;

 2.同样我们用循环控制好end就搞定了蓝色组的直接插入排序:

for (int j = 0; j < n - gap; j += gap){int end = j;int tmp = a[end + gap];for (end; end >= 0; end -= gap){if (tmp < a[end]){a[end + gap] = a[end];}else{break;}}a[end + gap] = tmp;}}

3.但是我们有gap组需要直接插入排序,那么我们再套一层循环循环gap次让不同组直接插入排序即可搞定预排序:

for (int i = 0; i < gap; i++){for (int j = i; j < n - gap; j += gap){int end = j;int tmp = a[end + gap];for (end; end >= 0; end -= gap){if (tmp < a[end]){a[end + gap] = a[end];}else{break;}}a[end + gap] = tmp;}}

这种写法是让同一组直接插入排好再排下一组。

 鼠鼠下面再展示一种写法,其实与上面写法本质是一样的:

for (int j = 0; j < n - gap; j ++){int end = j;int tmp = a[end + gap];for (end; end >= 0; end -= gap){if (tmp < a[end]){a[end + gap] = a[end];}else{break;}}a[end + gap] = tmp;}

这种写法其实是多组并列插入排序 ,老爷们体会一下,鼠鼠很难解释捏!

预排序的代码我们暂且写到这里,我们可以看到:gap越大,大的数据越快往后靠,小的数据越快往前靠;但是需排序乱序数组整体越不接近有序。gap越小,则相反;当gap小到等于1时,就是直接插入排序,能让需排序乱序数组直接变成有序的。

1.2.直接插入排序

我们经过一次预排序是不是直接就让需排序乱序数组来直接插入排序呢?

其实不是的,因为经过一次预排序不能保证需排序乱序数组接近有序,只能保证比没有预排序之前更加有序,经过一次预排序就直接让需排序乱序数组来直接插入排序的话效率没有多大提升!

而且如果只进行一次预排序的话,gap就是一个定值,gap是定值是不合适的。如果gap确定是3,但需排序乱序数组数据个数有10000个的话,每组就有300多个数据要排,不合适!

其实主流玩法已尽解决了这些个问题,只要进行多组预排序就行,我们来看希尔排序的完整代码再分析:

//希尔排序排升序
void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){gap = gap / 3 + 1;for (int j = 0; j < n - gap; j ++){int end = j;int tmp = a[end + gap];for (end; end >= 0; end -= gap){if (tmp < a[end]){a[end + gap] = a[end];}else{break;}}a[end + gap] = tmp;}}
}

这样子我们将gap设置成变化的,gap会越来越小,当gap不等于1时是预排序。相当于第一轮预排序大概是3个数据为一组排;第二轮预排序大概是9个数据为一组排;第三轮预排序是27个数据为一组排……而且每一轮预排序过后就越有序。

我们再分析发现,gap一定会变成1,那就是让需排序乱序数组直接来一把直接插入排序,这把直接插入排序过后循环结束并且需排序乱序数组就变成有序的了,而且经过了多次预排序最后来一把直接插入排序时间效率会很高!

当然gap如何变化都没有规定,我们也可以写成gap=gap/2……反正要保证最后一次循环的时候gap要等于1,才能保证最后一把是让需排序乱序数组整体进行直接插入排序。

我们来试试希尔排序得不得行:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>//希尔排序排升序
void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){gap = gap / 3 + 1;for (int j = 0; j < n - gap; j ++){int end = j;int tmp = a[end + gap];for (end; end >= 0; end -= gap){if (tmp < a[end]){a[end + gap] = a[end];}else{break;}}a[end + gap] = tmp;}}
}void PrintArray(int* a, int n)
{for (int i = 0; i < n; i++){printf("%d ", a[i]);}printf("\n");
}int main()
{int a[] = { 1,5,8,7,9,6,48,3,5,99,6,3,7,5 };PrintArray(a, sizeof(a) / sizeof(a[0]));ShellSort(a, sizeof(a) / sizeof(a[0]));PrintArray(a, sizeof(a) / sizeof(a[0]));return 0;
}

结果是没问题的!

2.希尔排序的时间复杂度

希尔排序有太多不确定性,所以时间复杂度不好计算,大多数人认为是O(N^1.3)。

3.希尔排序和直接插入排序的性能比较

也许老爷们会认为希尔排序弄那么多次预排序加一次直接插入排序,时间效率所不定还不如直接插入排序来的好。

其实不然,我们用一个程序比较比较就可以看出结果,这个程序用到一个C语言库里面的函数clock,clock函数的大致作用是获取从系统启动到调用这个clock函数之间的毫秒数。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<time.h>
#include<stdlib.h>//希尔排序排升序
void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){gap = gap / 3 + 1;for (int j = 0; j < n - gap; j ++){int end = j;int tmp = a[end + gap];for (end; end >= 0; end -= gap){if (tmp < a[end]){a[end + gap] = a[end];}else{break;}}a[end + gap] = tmp;}}
}//直接插入排序排升序
void InsertSort(int* a, int n)
{for (int j = 0; j < n - 1; j++){int end = j;int tmp = a[end + 1];for (end; end >= 0; end--){if (tmp < a[end]){a[end + 1] = a[end];}else{break;}}a[end + 1] = tmp;}
}int main()
{int n = 100000;int* a1 = (int*)malloc(sizeof(int) * n);int* a2 = (int*)malloc(sizeof(int) * n);srand((unsigned int)time(0));for (int i = 0; i < n; i++){a1[i] = rand();a2[i] = a1[i];}int begin1 = clock();ShellSort(a1, n);int end1 = clock();int begin2 = clock();InsertSort(a2, n);int end2 = clock();printf("ShellSort:%d\n", end1 - begin1);printf("InsertSort:%d\n", end2 - begin1);return 0;
}

我们看到结果,排序10万个一模一样的随机数,希尔排序用22毫秒,而直接插入排序用4490毫秒! 

感谢阅读!

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

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

相关文章

自动化运维工具---Ansible

一 Puppet Puppet是历史悠久的运维工具之一。它是一种基础架构即代码(laC)工具&#xff0c;使用户可以定义其基础 架构所需的状态&#xff0c;并使系统自动化以实现相同状态。 Puppet可监视用户的所有系统&#xff0c;并防止任何偏离已定义状态的情况。从简单的工作流程自动…

代码本地化

目的 代码本地化&#xff08;Localization&#xff09;是指将软件应用程序中的文本、图形、声音和其他内容翻译成特定语言的过程&#xff0c;同时确保这些内容在目标文化中适当地呈现。本地化不仅仅是对文本进行翻译&#xff0c;还包括对日期、时间、数字、货币、排序顺序、文本…

04-19 周四 GitHub CI 方案设计

04-19 周四 GitHub CI 方案设计 时间版本修改人描述2024年4月19日14:44:23V0.1宋全恒新建文档2024年4月19日17:22:57V1.0宋全恒完成部署拓扑结构的绘制和文档撰写 简介 需求 由于团队最近把代码托管在GitHub上&#xff0c;为解决推理、应用的自动化CI的需要&#xff0c;调研了…

最近惊爆谷歌裁员

Python团队还没解散完&#xff0c;谷歌又对Flutter、Dart动手了。 什么原因呢&#xff0c;猜测啊。 谷歌裁员Python的具体原因可能是因为公司在进行技术栈的调整和优化。Python作为一种脚本语言&#xff0c;在某些情况下可能无法提供足够的性能或者扩展性&#xff0c;尤其是在…

分析:Palo Alto在从SASE向SASO演进中定位不佳

摘要 我们通过上一篇文章&#xff08;Fortinet的愿景——超越SASE&#xff09;中应用于Fortinet的相同框架来回顾Palo Alto Network在网络和网络安全方面的前景。 SASE涉及数据传输的第一英里。不过&#xff0c;随着SASE的发展&#xff0c;投资者还需要考虑中间和最后一英里。…

【JavaScript】数据类型转换

JavaScript 中的数据类型转换主要包括两种&#xff1a;隐式类型转换&#xff08;Implicit Type Conversion&#xff09;和显式类型转换&#xff08;Explicit Type Conversion&#xff09;。 1. 隐式类型转换&#xff08;自动转换&#xff09;&#xff1a; js 是动态语言&…

Docker搭建LNMP+Wordpress的实验

目录 一、项目的介绍 1、项目需求 2、服务器环境 3、任务需求 二、Linux系统基础镜像 三、部署Nginx 1、建立工作目录 2、编写Dockerfile 3、准备nginx.conf配置文件 4、设置自定义网段和创建镜像和容器 5、启动镜像容器 6、验证nginx 三、Mysql 1、建立工作目录…

Kalign 3:大型数据集的多序列比对

之前一直用的是muscle&#xff0c;看到一个文章使用了Kalign&#xff0c;尝试一下吧 安装 wget -c https://github.com/TimoLassmann/kalign/archive/refs/tags/v3.4.0.tar.gz tar -zxvf v3.4.0.tar.gz cd kalign-3.4.0 mkdir build cd build cmake .. make make test su…

【数据结构与算法】之五道链表进阶面试题详解!

目录 1、链表的回文结构 2、相交链表 3、随机链表的复制 4、环形链表 5、环形链表&#xff08;||&#xff09; 6、完结散花 个人主页&#xff1a;秋风起&#xff0c;再归来~ 数据结构与算法 个人格言&#xff1a;悟已往之不谏&#xff0c;知…

【搜索技能】外链

文章目录 前言一、外链是什么&#xff1f;二、如何进行外链调查&#xff1f;总结 前言 今儿因为在搜索一个很感兴趣的软件&#xff0c;但是软件信息所在的网址非常有限。因此产生了一个念头&#xff1a;我能不能找到所有的包含了或者是引用了这个网站的网站呢? 调查之下&…

解密SSL/TLS:密码套件扫描仪的深度解析(C/C++代码实现)

解密SSL/TLS流量通常是为了分析和审计加密通信&#xff0c;以确保数据传输的安全性和合规性。密码套件扫描仪是实现这一目的的一种工具&#xff0c;它可以提供关于SSL/TLS配置的详细信息&#xff0c;帮助安全专家评估潜在的风险。 SSL/TLS协议基础 SSL/TLS协议是网络安全中不…

select,poll,epoll

在 Linux Socket 服务器短编程时&#xff0c;为了处理大量客户的连接请求&#xff0c;需要使用非阻塞I/O和复用&#xff0c;select&#xff0c;poll 和 epoll 是 Linux API 提供的I/O复用方式。 \selectpollepoll操作方式遍历遍历回调底层实现数组链表哈希表IO效率每次调用都进…

C语言/数据结构——每日一题(环形链表的约瑟夫问题)

一.前言 今天在牛客网上面看到了一道环形链表题&#xff0c;想着和大家们分享一下。可能我有点笨&#xff0c;那道题的链接我没搞好&#xff0c;所以很抱歉&#xff0c;只能麻烦大家们看一下截屏的题目信息了。废话不多数&#xff0c;让我们开始今天的题目分享吧。 二.正文 …

ComfyUI中的图像稀释处理

用下面的节点对图片进行稀释处理&#xff0c;如下 为0表示不变&#xff0c;我设置大一点&#xff0c;设置为0.5看看&#xff0c;如下 图像就暗淡了一些&#xff0c;但是还是有一些彩色的&#xff0c;相当于把它放在水里浸泡了一样&#xff0c;掉色了&#xff0c;这就是稀释&…

公网tcp转流

之前做过几次公网推流的尝试, 今天试了UDP推到公网, 再用TCP从公网拉下来, 发现不行, 就直接改用TCP转TCP了. 中间中转使用的python脚本, 感谢GPT提供技术支持: import socket import threadingdef tcp_receiver(port, forward_queue):"""接收TCP数据并将其放入…

LLM应用:工作流workflow创建自定义模版使用

参考: https://www.coze.cn/ 本案例是在coze平台上操作的,也有其他工具支持工作流的创建例如dify;也例如图像生成的comfyui工作流工具 创建自定义模版 可以根据自己需求创建自己的工作流工具;本文案例是创建一个联网搜索的LLM应用: 创建工作流页面: https://www.coze.c…

X 推出 Stories 功能,由 Grok AI 生成新闻摘要

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Python自动化测试【selenium面试题】

一、selenium中如何判断元素是否存在&#xff1f; expected_conditions模块提供了16种判断方法&#xff0c;以下方法是判断元素存在DOM中&#xff1a; presence_of_element_located """ An expectation for checking that an element is present on the DOM of…

分布式与一致性协议之ZAB协议(三)

ZAB协议 主节点崩溃了&#xff0c;怎么办&#xff1f; 众所周知&#xff0c;系统在运行中不可避免会出现各种各样的问题&#xff0c;比如进程崩溃了、服务器死机了&#xff0c;这些问题会导致很严重的后果&#xff0c;让系统没办法继续运行。在ZAB协议中&#xff0c;写请求是…

深度学习论文: DMAD: Dual Memory Bank for Real-World Anomaly Detection

深度学习论文: DMAD: Dual Memory Bank for Real-World Anomaly Detection DMAD: Dual Memory Bank for Real-World Anomaly Detection PDF: https://arxiv.org/pdf/2403.12362 PyTorch代码: https://github.com/shanglianlm0525/CvPytorch PyTorch代码: https://github.com/sh…