图解堆排序【一眼看穿逻辑思路】

P. S.:以下代码均在VS2019环境下测试,不代表所有编译器均可通过。
P. S.:测试代码均未展示头文件stdio.h的声明,使用时请自行添加。

  

目录

  • 1、堆的概念
  • 2、实现堆排序前的准备工作
  • 3、堆排序的思路
    • 3.1 第一步
    • 3.2 第二步
  • 4、结语

1、堆的概念


  在了解堆排序之前我们先要了解什么是堆:一个按照完全二叉树的储存方式存储的一维数组我们称之为堆。


在这里插入图片描述


  而堆又可以分为大堆和小堆。
  大堆:二叉树中的父结点在数值上都比子结点大。
  小堆:二叉树中的父结点在数值上都比子结点小。
  下图在就是一组较为明显的大小堆。

在这里插入图片描述

  故堆排序就是在堆的前提下进行排序。




2、实现堆排序前的准备工作


  我们需要完成的准备工作是实现一个关于二叉树即堆的向下调整函数,此处我们写为HeapAdjustDown。
void Swap(int* p1,int* p2) //简单的交换函数
{int* tmp = *p1;*p1 = *p2;*p2 = tmp;
}void HeapAdjustDown(int* a,int n,int parent)//a代表数组的地址,n为数组元素个数,parent为当前元素所在下标。
{int child = parent * 2 + 1;		//假设左孩子大于或小于右孩子.while(child < n)				//结束条件为到达最后一层时,最后一层没有子。{if(child + 1 < n && a[child + 1] > a[child])//判断左孩子是否真的大于或小于右孩子,如果不是{											//让child代表右边孩子的下标。++child;}if(a[child] > a[parent])	//判断父与子的关系,如果父大于或小于子,让其交换位置。{Swap(&a[child],&a[parent])parent = child;			//此处令交换的子的下标成为新的parent下标,即沿着交换路径一致进行//比较,直至到达最后一层。child = parent * 2 + 1;}else{break;					//当不满足大小条件是就会进来,即已经按照需求将堆排列成了大堆或者小堆。}}
}

  上面就是我们所完成的准备工作,其中
if(child + 1 < n && a[child + 1] < a[child])
if(a[child] < a[parent])

  这两条判断语句中的数组内成员比较可以更换比较符号。
  当使用 “ < ” 号时,第一条判断依据所筛选的时两个子中较小的一个。
           第二条判断语句就是比较所选的子是否小于父,如果小于就进行交换。
           这样进行调整后的堆就称之为小堆,即父皆比子小。
  当使用 “ > ” 号时,第一条判断依据所筛选的时两个子中较大的一个。
           第二条判断语句就是比较所选的子是否大于父,如果大于就进行交换。
           这样进行调整后的堆就称之为大堆,即父皆比子大。




3、堆排序的思路


3.1 第一步


  我们首先要做的就是将得到的数组进行调整,将其调整为大堆或者小堆。
  故写一个函数来进行操作较为方便:HeapSort
void HeapSort(int* a,int n)//此处的n为数组的元素个数
{for(int i = (n - 1 - 1) / 2; i >= 0; i--)//此处为何从(n - 1 - 1) / 2开始,后面会有图解,耐心一点哦~{//然后调用我们的向下调整函数。HeapAdjustDown(a,n,i);}
}

  到这里后,我们就完成了对数组的大堆或者小堆化,此处我们所进行的是大堆化处理。
  下面就进行我们此截止到目前的看图说话:
  假设我们所拥有的数组是{1,3,5,7,9,2,4,6,8,10}。
在这里插入图片描述  其在数组中和在堆中的存放方式如上图所示,我们按照上述代码执行。
在这里插入图片描述
  而后我们在数组元素9的基础上进行向下调整。
在这里插入图片描述
  这一步进行完后,我们的i–,此时的i = 3,也就是我们的元素7所在下标,故此时在数组元素7的基础上向下调整。
在这里插入图片描述
  故循环的意义就是从最后一层的父开始进行向下调整,一致循环到根位置,后面我们直接展示过程图,不在进行比较讲解。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  到此处我们的大堆构建也算完成了。
在这里插入图片描述
  根据VS验证我们所进行的数组大堆化也是正确无误的。
  此处又会有看官提出问题,我们为什么不从数组的头部开始进行向下调整呢,反而从尾部开始呢?
在这里插入图片描述
  我们直接上图,当我们从头部开始时,进行向下调整,得到的却不是大堆。这是因为:
在这里插入图片描述
  而后我们也同样直接展示过程图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  至此我们所得到的新数组也就和上述实验数组结果一致,为{5,9,4,8,10,2,1,6,7,3}。
  总而言之,我们不从头部开始进行向下调整,是因为以这样的方式进行时,每一次调整只会调整当前位置及当前位置向后的数据,而不会向前进行比较,会造成不可避免地bug。


3.2 第二步


  我们将数组大堆或小堆化后,就可以进行排序了,此时我们进行的是升序排列,排序的代码如下:
void HeapSort(int* a,int n)//此处的n为数组的元素个数
{for(int i = (n - 1 - 1) / 2; i >= 0; i--)//此处为何从(n - 1 - 1) / 2开始,后面会有图解,耐心一点哦~{//然后调用我们的向下调整函数。HeapAdjustDown(a,n,i);}int end = n - 1;		//原理下文解释while(end > 0){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);--end;}
}

  我们可以看到代码中创建了一个变量 “ end ”,其代表的含义为最后一个元素的数组下标,我们在前文中已经将数组进行了大堆化,故我们数组的第一个元素是大于其他元素的。
在这里插入图片描述
  此时我们将第一个数和最后一个数据交换位置,这样最大的数就处在了末尾,然后按照同样的方式对前面九个数字进行大堆化,这样就又会有一个第二大的数字排列在第一位,然后进行下一次循环,然后我们将 end–,进入下一次循环。下面我们展示过程图,并不在对途中内容进行讲解:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  依次向下进行最终就得到了如下的数组。
在这里插入图片描述

在这里插入图片描述
  通过验证我们可以得到上述方法是可行且正确无误的。
  从中我们也可以发现一个规律,我们通过创建大堆可以得到升序的序列,通过类比,我们明白也可以通过创建小堆可以得到降序的序列。




4、结语


  十分感谢您观看我的原创文章。
  本文主要用于个人学习和知识分享,学习路漫漫,如有错误,感谢指正。
  如需引用,注明地址。

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

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

相关文章

C++容器:list(双向链表)

一丶list介绍 C中的list容器底层确实是以双向链表的形式实现的。 list容器是C标准模板库&#xff08;STL&#xff09;中的一部分&#xff0c;它提供了对列表数据结构的实现。 双向链表结构&#xff1a;list容器的每个元素都是通过指针链接在一起的&#xff0c;每个元素都包含…

2024年中国国际厨卫家居展览会(上海KIB厨卫展)

中国国际厨卫家居博览会&#xff08;KIB&#xff09;由中国五金制品协会、中国国际贸易促进委员会轻工行业分会、北京奥维云网大数据科技股份有限公司主办。从最初的“中国国际橱柜、厨房卫浴产品与技术博览会(CIKB&#xff09;”&#xff0c;到2001年与中国国际五金展&#xf…

【2024系统架构设计】回顾历史,查缺补漏篇 ③

前言 hello,大家好: 💡💡💡 我们一起来备考软考高级系统架构设计师吧,本专栏提供综合知识、案例科目、论文(论点和部分示例范文)等内容,包括知识点总结和记忆小妙招哦。 🚀🚀🚀 可以减少资料查找和收集的时间,提高效率,我们一起集中精力学习干货吧! 💡…

k8s二进制部署--多master、负载均衡、高可用

目录 1、环境准备 1.1 服务器配置 1.2 master02 节点部署 2、负载均衡部署 2.1 下载nginx 2.2 修改nginx配置文件 2.3 启动nginx 2.3.1 检查配置文件语法 2.3.2 启动nginx服务&#xff0c;查看已监听6443端口 3. 部署keepalived服务(nginx主机&#xff0c;以nginx01为…

[ROS 系列学习教程] 建模与仿真 - URDF 建模实践

ROS 系列学习教程(总目录) 本文目录 一、机器人结构组成二、新建功能包三、编写launch文件四、创建底盘五、添加轮子六、添加其他部件七、解决部分实体位于地面以下的问题 前文介绍了URDF建模与URDF语法&#xff0c;接下来介绍怎么使用URDF从零构建一个机器人模型并在rviz中显示…

基于国产LoRa的智慧农业解决方案--ASR6601、SX1278

我国《数字乡村发展战略纲要》明确指出“要推进农业数字化转型”&#xff0c;加快推广云计算、大数据、物联网、人工智能在农业生产经营管理中的运用。 然而&#xff0c;目前我国的农业数字化转型还面临着诸多挑战。我国整体农业机械化程度和自动化控制水平仍然较低。由于农田面…

Java类和对象(二)—— 封装,static 关键字与代码块

前言 在面向对象的编程语言中&#xff0c;有三大特性&#xff1a;封装、继承和多态~~ 今天我们就来学习封装的知识 封装 什么是封装 在现实生活中&#xff0c;我们经常使用手机来进行沟通与交流&#xff0c;实际上我们拿到的手机是被封装好的&#xff0c;精美的屏幕&a…

java医院信息系统HIS源码SaaS模式Java版云HIS系统 接口技术RESTful API + WebSocket + WebService

java医院信息系统HIS源码SaaS模式Java版云HIS系统 接口技术RESTful API WebSocket WebService 云HIS是基于云计算的医疗卫生信息系统&#xff08;Cloud-Based Healthcare Information System&#xff09;&#xff0c;它运用云计算、大数据、物联网等新兴信息技术&#xff0c;…

jiebaNET中文分词器

最近我接手了一个有趣的需求&#xff0c;需要对用户评价进行分词&#xff0c;进行词频统计和情绪分析&#xff0c;并且根据词频权重制成词云图以供后台数据统计&#xff0c;于是我便引入了jieba分词器,但是我发现网上关于jiebaNET相关文档实在太少了&#xff0c;甚至连配置文件…

core.sshd.xxxxxx文件过大

背景 【紧急】【应用分组】应用: 接入点服务, 分组: 观众预发, ip: xx.xx.xx.xx 【/】&#xff0c;磁盘使用率已连续2次大于90% [当前值:100%]。报警时间: 2024-05-13 14:07:01 原因 登录机器查看&#xff0c;发现根目录下有大量的崩溃文件将 / 打满 处理 1&#xff0c; 删…

百度百舸 AIAK-LLM 的大模型训练和推理加速实践

本文整理自 4 月 16 日的 2024 百度 Create 大会的公开课分享《百舸 AIAK-LLM&#xff1a;大模型训练和推理加速实践》。 今天要分享的主题是 AI Infra 相关的内容&#xff0c;主要内容分为四部分。 首先和大家一起讨论大模型给基础设施带来的挑战。第二部分则是向大家介绍一个…

洗地机怎么挑?洗地机选购指南,2024洗地机测评选购攻略

在快节奏的生活中&#xff0c;繁琐的清洁工作往往令人头疼&#xff0c;随着洗地机的诞生&#xff0c;极大地简化了清洁的过程&#xff0c;洗地机凭借着它吸拖洗为一体的高效清洁特点&#xff0c;受到家庭和商业场所的广泛欢迎。那么&#xff0c;洗地机怎么挑&#xff0c;要注意…