0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C语言排序中堆排序的技巧

C语言编程学习基地 ? 来源:C语言编程学习基地 ? 作者:C语言编程学习基地 ? 2021-07-29 15:29 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

对于堆的操作通常需要以下3个步骤:

最大堆调整(Max Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点

创建最大堆(Build Max Heap):将堆中的所有数据重新排序

堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算。

C代码实现

920e4226-edfd-11eb-a97a-12bb97331649.png

代码看起来比较抽象,将代码运行时数据交换的过程打印出来,然后结合二叉树的图形来分析,就会比较好理解了。代码运行过程中数据交换过程如下:

923d3004-edfd-11eb-a97a-12bb97331649.png

为了方便观看这里使用二叉树图形生成软件,通过二叉树图形来观察数据交换过程。二叉树图形生成使用的是一个在线生成网站:mshang.ca/syntree 后面所有的二叉树图形都使用此软件生成。

代码一开始首先打印出原始数据

数组元素 0 8 1 5 4 3 7 9 2 6 将这10个数据在网站上使用公式生成二叉树的图表,软件界面如下:

93a8ed3e-edfd-11eb-a97a-12bb97331649.png

首先将数组从上至下按顺序排列,转换成二叉树。

公式:0[8 [5 9[2]][4[6]]] [1[3] [7 ]]]

转换成二叉树之后,需要让这个无序堆变成最大堆,也就是每个堆都实现父节点的值大于任何一个子节点值。从最后一个堆开始,依次比较父节点和子节点的值,如果子节点值大于父节点值,就需要交换。

9435a3b4-edfd-11eb-a97a-12bb97331649.png

创建最大堆: 6为最后一个子节点,所以从6开始依次和父节点比较,如果子节点大于父节点,就需要交换子节点和父节点的位置。从设备树图形中可以看出,子节点6大于父节点4,所以需要交换子节点的父节点的位置。

公式:0[8 [5 9[2]][6[4]]] [1[3] [7 ]]]

交换 6 和4

6交换完成后,接下来依次向前比较其他子节点,6前面的节点是2,2小于父节点5,继续向前查找子节点9,子节点9大于父节点5,所以就交换9和5的位置。

公式:0[8 [9 5[2]][6[4]]] [1[3] [7 ]]]

交换9和5

接下来继续向前查找,发现子节点7大于父节点1,继续交换。

公式:0[8 [9 5[2]][6[4]]] [7[3] [1 ]]]

交换7和1

继续向前查找发现子节点9大于父节点8,交换位置。

公式:0[9 [8 5[2]][6[4]]] [7[3] [1 ]]]

交换9和8

继续比较其他节点

公式:9[0 [8 5[2]][6[4]]] [7[3] [1 ]]]

交换9和0

公式:9[8 [0 5[2]][6[4]]] [7[3] [1 ]]]

交换8和0

公式:9[8 [5 0[2]][6[4]]] [7[3] [1 ]]]

交换5和0

此时最大堆已经创建完成,此时根节点的数字9就是数组中的最大值。

代码中打印出来的数据顺序和通过二叉树图形分析出来的顺序完全一样。此时最大堆调整已经完成了。接下来就需要开始堆排序,依次将根节点的数据存放到最后一个节点,形成一个有序堆。

9592b544-edfd-11eb-a97a-12bb97331649.png

堆排序(最大堆调整)

首先交换数组中第一个元素,和排序好的前一个元素位置。此时数组中的第一个元素是9,排序完成之后最后一个元素是4,交换9和4.

95afbbda-edfd-11eb-a97a-12bb97331649.png

公式:4[8 [5 0[2]][6[9]]] [7[3] [1 ]]]

交换9和4

交换完成后,此时最大值9所在的底部位置就成为了有序区,有序区之后就不会参与任何对比。接下来继续调整父节点和子节点,确保父节点要大于子节点。

公式:8[4 [5 0[2]][6[9]]] [7[3] [1 ]]]

交换8和4

公式:8[6 [5 0[2]][4[9]]] [7[3] [1 ]]]

交换6和4

此时数字8称为了根节点,是目前无序区中的最大值,将8和底部区的2交换,将当前最大值8放到有序区中。

公式:2[6 [5 0[8]][4[9]]] [7[3] [1 ]]]

交换8和2

此时8已经存放到了有序区中,此后就不参与任何交换了。此时2变为根节点后,需要在重新调整一次节点,确保父节点大于子节点。

公式:7[6 [5 0[8]][4[9]]] [2[3] [1 ]]]

交换7和2

公式:7[6 [5 0[8]][4[9]]] [3[2] [1 ]]]

交换3和2

此时数字7变为根节点,是无序区间的最大值。需要将根节点的数字移动到有序区中。

将根节点7和0交换位置。

公式:0[6 [5 7[8]][4[9]]] [3[2] [1 ]]]

交换7和0

接下来重新调整节点 公式:6[0 [5 7[8]][4[9]]] [3[2] [1 ]]]

交换6和0

公式:6[5 [0 7[8]][4[9]]] [3[2] [1 ]]]

交换5和0

此时6变为了根节点,是无序区间的最大值。

将根节点和有序区间的前一个数字交换,也就是1和6需要交换。

公式:1[5 [0 7[8]][4[9]]] [3[2] [6 ]]]

交换6和1

接下来重新调节一次节点

公式:5[1 [0 7[8]][4[9]]] [3[2] [6 ]]]

交换5和1

公式:5[4 [0 7[8]][1[9]]] [3[2] [6 ]]]

交换4和1

此时5变成的根节点,需要将5移动到有序队列中去。

接下来需要交换根节点5和无序节点2的位置

公式:2[4 [0 7[8]][1[9]]] [3[5] [6 ]]]

交换5和2

重新调整节点位置

公式:4[2 [0 7[8]][1[9]]] [3[5] [6 ]]]

交换4和2

此时4是无序列表中的最大值,需要交换4和1的位置

公式:1[2 [0 7[8]][4[9]]] [3[5] [6 ]]]

交换4和1

重新调整节点位置

公式:9[2 [0 6[7]][3[8]]] [1[4] [5 ]]]

交换3和1

此时3为无序列表中最大值,需要交换3和0的位置。

公式:0[2 [3 7[8]][4[9]]] [1[5] [6 ]]]

交换3和0

交换完成后重新调整节点位置 公式:9[0 [2 6[7]][3[8]]] [1[4] [5 ]]]

交换2和0

此时2变成了无序列表中最大值,1为有序列表的前一个值,交换2和1的位置。

公式:1[0 [3 7[8]][4[9]]] [2[5] [6 ]]]

交换2和1

此时1是根节点,无序列表中就剩0一个数字了,交换1和0。

公式:0[1 [3 7[8]][4[9]]] [2[5] [6 ]]]

9a890706-edfd-11eb-a97a-12bb97331649.png

交换1和0

这是0变成了根节点,而其他的所有数字都在有序列表中,无序列表中已经没有数字了,此时说明排序完成。

9acd8d9a-edfd-11eb-a97a-12bb97331649.png

可以看出最好、最坏、一般情况下数据移动的次数和方法基本都差不多。

接下来随机生成10000个数据,看看排序需要多长时间。

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7633

    浏览量

    142169

原文标题:【数据结构】C语言排序方法——堆排序详解!

文章出处:【微信号:cyuyanxuexi,微信公众号:C语言编程学习基地】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    国际首创新突破!中国团队以存算一体排序架构攻克智能硬件加速难题

    2025 年 6 月 25 日,北京大学团队在智能计算硬件方面取得领先突破,国际上首次实现了基于存算一体技术的高效排序硬件架构 (A fast and reconfigurable
    的头像 发表于 07-02 16:50 ?253次阅读
    国际首创新突破!中国团队以存算一体<b class='flag-5'>排序</b>架构攻克智能硬件加速难题

    Analog Devices Inc. MAX16895 监控电路特性/应用/功能图

    Analog Devices MAX16895监控电路是小型、低功耗、电压监控电路,具有排序功能。这些器件具有可调的、低至0.5V的电压监控阈值,并可利用外部电容调节延迟时间。这些Analog Devices器件非常适合用于电源排序、复位
    的头像 发表于 06-26 09:34 ?170次阅读
    Analog Devices Inc. MAX16895 监控电路特性/应用/功能图

    低成本电源排序器解决方案

    绝大多数负载点DC-DC转换器可以将上一个转换器的电源就绪输出连接至下一个转换器的使能输入,实现上电排序。这种方法只适合比较简单的设计,不能满足多数现代微处理器和DSP的要求一这类器件要求断电顺序必须与上电顺序相反。许多厂商针对这类应用推出了可编程排序IC,但器件价格较为
    的头像 发表于 05-21 09:55 ?599次阅读
    低成本电源<b class='flag-5'>排序</b>器解决方案

    深入理解C语言C语言循环控制

    C语言编程,循环结构是至关重要的,它可以让程序重复执行特定的代码块,从而提高编程效率。然而,为了避免程序进入无限循环,C语言提供了多种循
    的头像 发表于 04-29 18:49 ?1250次阅读
    深入理解<b class='flag-5'>C</b><b class='flag-5'>语言</b>:<b class='flag-5'>C</b><b class='flag-5'>语言</b>循环控制

    C语言的历史及程序介绍

    电子发烧友网站提供《C语言的历史及程序介绍.pdf》资料免费下载
    发表于 04-09 16:10 ?0次下载

    详解Linux sort命令之掌握排序技巧与实用案例

    在linux系统使用过程,提供了sort排序命令,支持常用的排序功能。 常用参数 sort命令支持很多参数,常用参数如下: ? 短参数 长参数 说明 -n – number-sort 按字符串数值
    的头像 发表于 01-09 10:10 ?1018次阅读

    TimSort:一个在标准函数库中广泛使用的排序算法

    在计算机科学的领域,排序算法是每位学生必学的基础,而排序的需求是每位程序员在编程过程中都会遇到的。 在你轻松调用 .sort() 方法对数据进行排序时,是否曾好奇过,这个简单的方法背后使用的是哪种
    的头像 发表于 01-03 11:42 ?634次阅读

    解读版|Air780E软件C语言内存数组的神秘面纱!

    今天我们来揭开Air780E 软件 C 语言内存数组的神秘面纱,希望有所收获。
    的头像 发表于 11-17 10:00 ?693次阅读
    解读版|Air780E软件<b class='flag-5'>中</b><b class='flag-5'>C</b><b class='flag-5'>语言</b>内存数组的神秘面纱!

    C语言指针学习笔记

    本文从底层内存分析,彻底让读者明白C语言指针的本质。
    的头像 发表于 11-05 17:40 ?693次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言</b>指针学习笔记

    C语言C++结构体的区别

    同样是结构体,看看在C语言C++中有什么区别?
    的头像 发表于 10-30 15:11 ?825次阅读

    C语言与Java语言的对比

    C语言和Java语言都是当前编程领域中的重要成员,它们各自具有独特的优势和特点,适用于不同的应用场景。以下将从语法特性、内存管理、跨平台性、性能、应用领域等多个方面对C
    的头像 发表于 10-29 17:31 ?1152次阅读

    C语言与其他编程语言的比较

    C语言作为一种历史悠久的编程语言,自其诞生以来,一直在软件开发领域扮演着重要角色。它以其高效、灵活和可移植性强的特点,成为了系统级编程的首选语言之一。
    的头像 发表于 10-29 17:30 ?1161次阅读

    时间复杂度为 O(n^2) 的排序算法

    作者:京东保险 王奕龙 对于小规模数据,我们可以选用时间复杂度为 O(n2) 的排序算法。因为时间复杂度并不代表实际代码的执行时间,它省去了低阶、系数和常数,仅代表的增长趋势,所以在小规模数据情况下
    的头像 发表于 10-19 16:31 ?1796次阅读
    时间复杂度为 O(n^2) 的<b class='flag-5'>排序</b>算法

    TPS54120排序和跟踪

    电子发烧友网站提供《TPS54120排序和跟踪.pdf》资料免费下载
    发表于 10-10 10:54 ?0次下载
    TPS54120<b class='flag-5'>排序</b>和跟踪

    hex文件如何查看原c语言代码

    是处理器可以直接执行的指令,而 C 语言代码则是人类可读的高级编程语言代码。 然而,如果你想要从 .hex 文件获取一些有用的信息或者对程序进行分析,你可以考虑以下几种方法: 反汇编
    的头像 发表于 09-02 10:37 ?5115次阅读