news 2026/7/3 21:06:01

希尔排序与堆排序

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
希尔排序与堆排序

希尔排序

介绍

希尔排序由希尔发明,当一个序列的无序程度较低时,那么使用插入排序的效率就会很快,希尔排序的核心思想就是,通过逐步缩小增量(步长)来逐步把一开始很无序的序列慢慢变得有序,最后当增量为1时,就是一次典型的插入排序。

实现

typedef int ElementType; void ShellSort(ElementType A[], int N) { int i,j,Increment; ElementType tmp; for (Increment=N/2; Increment>0; Increment/=2) { for (i=Increment; i<N; i++) { tmp = A[i]; for (j=i; j>=Increment; j-=Increment) { if (tmp < A[j-Increment]) { A[j] = A[j-Increment]; }else { break; } } A[j] = tmp; } } }

假如有一个元素数量为11的乱序序列,那么就可以得到11/2=5,5/2=2,2/1=1,这三个增量。对序列进行增量为5的插入排序,分别获得下标为(5,0),(6,1),(7,2),(8,3),(9,4),(10,5)这六组下标的跳跃步长为5的序列,然后分别对这六组序列进行插入排序,排完序后的整个数列的有序程度就会升高一些,这样就可以提高之后进行直接插入排序的效率了。

接着进行增量为2的插入排序,分别获得下标为(2,0),(3,1),(4,2,0),(5,3,1),(6,4,2,0),(7,5,3,1),(8,6,4,2,0),(9,7,5,3,1),(10,8,6,4,2,0)这九组下标的跳跃步长为2的序列,再分别对这九组序列进行插入排序,排序完后整个序列的有序程度就很高了。看似这一轮的比较次数很多,但其实还有个break语句,其表示若第一次比较不交换时,那就不进行后续的比较了,例如(4,2,0),若下标为4和2的不需要交换,那说明下标为4,2,0的就已经是有序了,不需要再对2,0进行比较了。若下标为4,2的进行交换了,那还得继续比较下标为4和0的元素。

算法中第一个for循环得到增量矩阵,第二个for循环获得各个分序列中的首元素的下标,第三个for循环对各个分序列进行插入排序。

分析

希尔排序是不稳定排序,其会把不同步长的分序列进行排序,当相同元素被分到不同分序列中时,可能会改变它们的相对位置。

不同步长序列的时间复杂度不一样,若为n/2,n/4....1的步长的话,那最坏的时间复杂度为O().若用Hibbard步长序列(-1),那时间复杂度为O().若用Sedgewick步长序列(混合序列9×-9×+1和-3×+1),那最坏的情况下时间复杂度被优化成O()了。

堆排序

介绍

在之前的文章中介绍了堆这一数据结构,得益于堆的特性,其根节点始终是最大值(或最小值),我们可以不停的取堆的根节点元素然后按顺序排好,这样就可以得到排好序的序列了。

实现

typedef int ElementType; #define LeftChild(i) (2*(i)+1) void Swap(ElementType *a, ElementType *b) { ElementType temp = *a; *a = *b; *b = temp; } void PercDown(ElementType A[],int i,int N) { int Child; ElementType Tmp; for (Tmp = A[i];LeftChild(i)<N;i=Child) { Child = LeftChild(i); if (Child!=N-1 && A[Child+1]>A[Child]) { Child++; } if (Tmp<A[Child]) { A[i] = A[Child]; }else { break; } } A[i] = Tmp; } void HeapSort(ElementType A[],int N) { int i; for (i=N/2;i>=0;i--) { PercDown(A,i,N); } for (i=N-1;i>0;i--) { Swap(&A[0],&A[i]); PercDown(A,0,i); } }

得益于堆对应完全二叉树父子节点位置的数学关系,我们可以通过对原始无序序列进行下滤操作从而将其转化成符合堆结构的数组。

此时这个数组的第一个元素是整个序列的最大值,把它和最后的元素进行交换,这样整个序列中,我们完成了最大元素的归位。然后在把除最后元素的其他所有元素进行下滤操作重新形成新堆,再把第一个元素放到倒数第二个位置上,这样就完成了第二个最大元素的归位,循环往复就以从大到小的顺序完成了排序操作。

分析

堆排序是不稳定的,当把栈顶元素和最后有个元素进行交换时,可能会改变相同元素的相对位置。

要进行n-1次交换,每次交换都得重新通过下滤操作构建堆结构(该构建操作的时间复杂度为 O(LogN)),所以一共是O(NLogN)。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/2 14:17:00

Calibre-Douban插件:元数据管理与电子书整理的高效解决方案

还在为电子书信息缺失而抓狂吗&#xff1f;每次手动输入书籍信息都让你感到效率低下&#xff1f;Calibre-Douban插件作为一款专业的Calibre插件&#xff0c;通过智能化的自动化工具&#xff0c;彻底解放你的双手&#xff0c;让电子书整理变得轻松高效。 【免费下载链接】calibr…

作者头像 李华
网站建设 2026/7/1 6:48:11

31、集群架构全解析:类型、配置与最佳实践

集群架构全解析:类型、配置与最佳实践 1. 集群软件概述 集群软件能够创建单一系统映像,并将任务分配到所有节点上并发执行。任务通过消息传递库进行协调,结果也通过该库进行通信。常见的集群软件应用示例包括 Oracle Real Application Clusters (RAC) 和 IBM Sysplex Data…

作者头像 李华
网站建设 2026/6/29 23:51:52

AI Agent领域的痛点与创新解决方案

AI Agent领域的痛点与创新解决方案 目录 AI Agent领域的痛点与创新解决方案 一、核心痛点问题 1. 推理能力局限:"想不深、连不上" 2. 成本与效率悖论:"算不起、等不及" 3. 上下文管理困境:"记不住、理不清" 4. 可靠性危机:"说胡话、做傻…

作者头像 李华
网站建设 2026/7/1 19:00:21

44、网络安全之防火墙与病毒防护全解析

网络安全之防火墙与病毒防护全解析 1. 防火墙的控制方法 防火墙在企业网络中起着至关重要的作用,它能够对员工使用内部服务器以及外部人员访问公司服务器的方式进行严格控制。防火墙主要通过以下三种方法来控制网络流量: - 数据包过滤 :对每个进出的数据包进行检查,依…

作者头像 李华
网站建设 2026/7/2 10:39:41

50、未来信息技术趋势:关键技术解析与应用前景

未来信息技术趋势:关键技术解析与应用前景 1. 网络融合技术 网络融合技术将存储和语音等服务集成到 IP 网络中,有助于降低设置和支持成本。通过这种集成,组织能够利用现有的网络进行应用程序、存储和电话通话等操作。同时,不同的服务团队可以合并,从而减少人员和维护成本…

作者头像 李华
网站建设 2026/6/30 22:02:08

快速掌握yt-dlp-gui:Windows视频下载终极指南

快速掌握yt-dlp-gui&#xff1a;Windows视频下载终极指南 【免费下载链接】yt-dlp-gui Windows GUI for yt-dlp 项目地址: https://gitcode.com/gh_mirrors/yt/yt-dlp-gui 在数字内容爆炸的时代&#xff0c;高效获取网络视频资源已成为许多用户的迫切需求。yt-dlp-gui作…

作者头像 李华