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

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.mzph.cn/web/12843.shtml

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

相关文章

音视频捕捉技术:LCC382 SDI采集卡深度解析

在日新月异的多媒体时代&#xff0c;高质量的音视频采集已成为众多领域不可或缺的一环。为此&#xff0c;灵卡科技精心打造了LCC382 —— 一款集高效性、灵活性与前沿技术于一身的SDI输入与环出、HDMI输出音视频采集卡&#xff0c;旨在满足从专业直播、视频会议到医疗影像、安防…

网页版Figma汉化

最近学习Figma&#xff0c;简单介绍一下网页版Figma的汉化方法 1.打开网址&#xff1a;Figma软件汉化-Figma中文版下载-Figma中文社区 2.下载汉化插件离线包 解压汉化包 3.点开谷歌的管理扩展程序 4.点击加载已解压的扩展程序&#xff0c;选择刚刚解压的包 这样就安装好了汉化…

QT状态机2-含终止状态的嵌套状态机

#include "MainWindow.h" #include "ui_MainWindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)

前馈神经网络FNN、多层感知机MLP和反向传播推导

目录 一、前馈神经网络FNN 激活函数的使用 二、多层感知机MLP MLP的典型结构 多层感知机MLP的特点 和前馈神经网络FNN的区别 三、传播推导 1、前向传播(Forward propagation) &#xff08;1&#xff09;输入层到隐藏层 &#xff08;2&#xff09;隐藏层到输出层 2、…

Java面试八股之WeakHashMap的工作原理

简述WeakHashMap的工作原理 弱键&#xff08;Weak Keys&#xff09;&#xff1a; WeakHashMap 的键&#xff08;keys&#xff09;是通过 WeakReference 弱引用进行封装的。弱引用是一种特殊的引用类型&#xff0c;它不会阻止所引用的对象被垃圾收集器回收。这意味着&#xff…

冥想训练具体方法有哪些|流静冥想

冥想是一种身体的放松和敏锐的警觉性相结合的状态。 每日练习的好处远不止你花在集中注意力的那几分钟。桑托雷利是建在乌斯特的马萨诸塞大学医学院的减压诊所的所长&#xff0c;她也是《自愈》的作者&#xff0c;她说&#xff1a;"冥想是一种工具&#xff0c;通过练习&a…

ubuntu无法远程连接,ssh不可用,ssh远程连接被拒绝的解决方法。启动sshd远程连接

1、用以下命令检查ssh状态 systemctl status sshd2、如果查不到sshd状态&#xff0c;或提示没有ssh&#xff0c;就安装ssh服务器和客户机 $ sudo apt install openssh-server # 安装ssh服务器 $ sudo apt install openssh-client # 安装ssh客户机3、如果不能安装openssh-…

构建安全的GenAI/LLMs核心技术解密之大模型对抗攻击(一)

LlaMA 3 系列博客 基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (一) 基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (二) 基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (三) 基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (四) 基于 LlaMA…

云手机的优缺点分析

云手机&#xff0c;作为云计算领域的创新&#xff0c;致力于提供更为灵活的移动设备体验&#xff0c;特别适用于那些希望在不同设备之间无缝切换的用户。虽然云手机带来了一系列优势&#xff0c;但也伴随着一些挑战&#xff0c;比如网络延迟可能会影响用户体验&#xff0c;特别…

网络安全|隐藏IP地址的5种不同方法

隐藏计算机的IP地址在互联网在线活动种可以保护个人隐私&#xff0c;这是在线活动的一种常见做法&#xff0c;包括隐私问题、安全性和访问限制内容等场景。那么如何做到呢?有很5种方法分享。每种方法都有自己的优点和缺点。 1. 虚拟网络 当您连接到虚拟服务器时&#xff0c;您…

openGauss学习笔记-284 openGauss AI特性-AI4DB数据库自治运维-DBMind模式说明-component子命令

文章目录 openGauss学习笔记-284 openGauss AI特性-AI4DB数据库自治运维-DBMind模式说明-component子命令284.1 命令参考openGauss学习笔记-284 openGauss AI特性-AI4DB数据库自治运维-DBMind模式说明-component子命令 该子命令可以用于启动DBMind的组件,包括可用于监控指标的…

Dubbo配置上的一些概念

对于dubbo在spring中我们可能看到有如下配置&#xff08;可参考Schema 配置参考手册 | Apache Dubbo&#xff09;&#xff1a; dubbo:application:id: dubbo-account-examplename: dubbo-account-example# 是否启用 Dubbo 的 QoS&#xff08;Quality of Service&#xff09;服…

Blender雕刻建模_笔刷

1.雕刻模式 雕刻Scuplt&#xff0c;一种常用的建模方式 -选中物体&#xff0c;进入雕刻模式 -重构网格&#xff08;修改体素大小&#xff0c;点击重构网格&#xff09;给物体添加更多面 -选择笔刷&#xff0c;雕刻 -退出雕刻模式 2.重构网格 一种按体积的细分方式&#xf…

openstack部署nova中出现的问题:

[rootcontroller nova]# su -s /bin/sh -c “nova-manage db sync” nova /usr/lib/python2.7/site-packages/pymysql/cursors.py:170: Warning: (1831, u’Duplicate index block_device_mapping_instance_uuid_virtual_name_device_name_idx. This is deprecated and will be…

Springboot+MybatisPlus如何实现带验证码的登录功能

实现带验证码的登录功能由两部分组成&#xff1a;&#xff1a;1、验证码的获取 2、登录&#xff08;进行用户名、密码和验证码的判断&#xff09; 获取验证码 获取验证码需要使用HuTool中的CaptchaUtil.createLineCaptcha()来定义验证码的长度、宽度、验证码位数以及干扰线…

【JavaScript】严格模式

严格模式&#xff08;Strict Mode&#xff09;是一种运行模式&#xff0c;它提供了一种更加严格的语法和错误检查&#xff0c;以帮助开发者编写更可靠、更规范的代码。 什么是严格模式&#xff1a; 严格模式是一种 JavaScript 的执行模式&#xff0c;通过启用严格模式&#xff…

这个notebook集合,赞

这几天在Github上看到一个数据科学仓库&#xff0c;汇总了很多Python notebook代码&#xff0c;主要是数据方向。 项目地址&#xff1a; https://github.com/donnemartin/data-science-ipython-notebooks 其中包括了pandas、numpy、matplotlib、scikit-learn、tensorflow、sp…

【Xilinx】程序可以综合实现,但无法生成bit文件

项目场景&#xff1a; 使用xilinx vivado过程中遇到以下问题&#xff1a; 程序可以综合实现&#xff0c;但无法生成bit文件 问题描述 最终生成bit文件时报错如下 [DRC PDCN-1567] BUFGCTRL_CE_pins_both_connected_to_gnd: For cell ***/rxrecclk_bufg_i placed at site BU…

c++ visualstudio2017 opencv debug源码 windows配置

源码下载和cmake opencv源码和opencv-contribue文件夹的层级目录 在opencv-4.4.0中新建build文件夹&#xff0c;并启动cmake-gui 配置如下&#xff0c;使用vs2017 x64, 需要注意contrib文件夹的设置&#xff0c;如下方蓝色所示&#xff0c;依次点击Configure和Generate 在bu…

半小时搞懂STM32知识点——UART

1.UART 1.1为什么要使用UART这种协议?介绍一下UART及其特点 成本低&#xff0c;硬件简单&#xff0c;数据格式灵活&#xff1b; 低速全双工异步串行通信 1.2 UART数据帧格式&#xff1f; 起始位&#xff08;1&#xff09;&#xff0b;数据位&#xff08;5-8&#xff09; 校验位…