数据结构:大顶堆、小顶堆

堆是其中一种非常重要且实用的数据结构。堆可以用于实现优先队列,进行堆排序,以及解决各种与查找和排序相关的问题。本文将深入探讨两种常见的堆结构:大顶堆和小顶堆,并通过 C++ 语言展示如何实现和使用它们。

一、定义

堆是一种完全二叉树。完全二叉树的定义:所有节点从上往下,从左往右的依次排列,不能有空位置,是为完全二叉树。

下面是完全二叉树和不完全二叉树的示意图:
在这里插入图片描述

大顶堆:
根节点(堆顶元素)是所有节点中的最大值(父节点都大于左右子节点)。大顶堆常用于实现优先队列,且可用于构建堆排序算法。

小顶堆:
小顶堆中的根节点是所有节点中的最小值(父节点都小于左右子节点)。小顶堆常用于问题如:查找流中的前 K 个最小元素。
在这里插入图片描述

二、实现

通常用 数组 来实现:具体方法就是将二叉树的结点按照 层级顺序 放入数组中, 根结点在 位置1(数组索引0处不存储数据),它的子结点在位置2和3,而子结点的子结点则分别在位置4,5,6和7,以此类推
在这里插入图片描述

  • 如果一个结点的位置为 k,则它的父结点的位置为 k/2
  • 两个子结点的位置则分别为 2k 和 2k+1

2.1 Insert

堆是用 数组 完成数据元素的存储的,由于数组的底层是一串连续的内存地址,所以要往堆中插入数据,只能往数组中从索引0处开始,依次往后存放数据,但是堆中对元素的顺序是有要求的,每一个结点的数据要 大于等于它的两个子结点的数据,所以每次插入一个元素,都会使得堆中的数据顺序变乱,这个时候就需要通过一些方法,让刚才插入的这个数据放入到合适的位置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
所以,如果往堆中新插入元素,只需要不断的比较新结点 a[k] 和它的父结点 a[k/2] 的大小,然后根据结果完成数据元素的交换,就可以完成堆的有序调整。

2.1 delMax

由大顶堆的特性可以知道,索引1处的元素,也就是根结点就 是最大的元素,把根结点的元素删除后,需要有一个新的根结点出现,这时可以 暂时把堆中最后一个元素放到索引1处,充当根结点,但是它有可能不满足堆的有序性需求,这个时候就需要通过一些方法,让这个新的根结点放入到合适的位置
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
所以,当删除掉最大元素后,只需要将最后一个元素放到索引1处,并不断的拿着当前结点 a[k] 与它的子结点a[2k] 和 a[2k+1] 中的较大者交换位置,即可完成堆的有序调整。

三、堆排序

要求:给你一个数组 {4,6,8,5,9} , 要求使用堆排序法,将数组升序排序。

实现步骤:

  • 构造堆
  • 得到堆顶元素,这个值就是最大值
  • 交换堆顶元素和数组中的最后一个元素,此时所有元素中的最大元素已经放到合适的位置
  • 对堆进行调整,重新让除了最后一个元素的剩余元素中的最大值放到堆顶
  • 重复2~4这个步骤,直到堆中剩一个元素为止

3.1 堆构造过程

堆的构造,最直观的想法就是另外再创建一个新数组,然后从左往右遍历原数组,每得到一个元素后,添加
到新数组中,并通过上浮,对堆进行调整,最后新的数组就是一个堆

上述的方式虽然很直观,也很简单,但是可以用更聪明一点的办法完成它

创建一个新数组,把原数组0 ~ length-1的数据拷贝到新数组的 1 ~ length 处,再从新数组 长度的一半 处开始往 1索引 处扫描(从右往左),然后对扫描到的每一个元素做下沉调整即可

为什么是新数组长度的一半?

因为新数组是一个无序堆,长度的一半之后的结点为叶子结点;叶子结点不需要要下沉调整

1.假设给定无序序列结构如下:
在这里插入图片描述
2.此时我们从最后一个非叶子结点开始(叶结点自然不用调整,第一个非叶子结点arr.length/2-1=5/2-1=1,也就是下面的6结点),从左至右,从下至上进行调整。

在这里插入图片描述
3.找到第二个非叶节点4,由于[4,9,8]中9元素最大,4和9交换。
在这里插入图片描述
4.这时,交换导致了子根[4,5,6]结构混乱,继续调整,[4,5,6]中6最大,交换4和6。

在这里插入图片描述

3.2 堆排序过程

对构造好的堆,只需要做 类似于堆的删除操作,就可以完成排序:

  1. 将堆顶元素和堆中最后一个元素交换位置
  2. 通过对堆顶元素下沉调整堆,把最大的元素放到堆顶 (此时最后一个元素不参与堆的调整,因为最大的数据已经到了数组的最右边)
  3. 重复1~2步骤,直到堆中剩最后一个元素

1.将堆顶元素9和末尾元素4进行交换
在这里插入图片描述

2.重新调整结构,使其继续满足堆定义
在这里插入图片描述

3.再将堆顶元素8与末尾元素5进行交换,得到第二大元素8
在这里插入图片描述
4.后续过程,继续进行调整,交换,如此反复进行,最终使得整个序列有序
在这里插入图片描述

3.3 总结堆排序的基本思路

1).将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆
2).将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端:
3).重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤
直到整个序列有序。

至于完整的代码实现和动画显示,可以参考我的文章 - 排序算法基础

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

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

相关文章

利用操作符解题的精彩瞬间

下面是链接为了解释练习2的并且还有与操作符相关的知识。 C语言与操作符相关的经典例题-CSDN博客 操作符详解(上)-CSDN博客 操作符详解(下)-CSDN博客 目录 练习1:在一个整型数组中,只有一个数字出现一…

Vue学习笔记(二)快速入门

Vue学习笔记&#xff08;二&#xff09;快速入门 vue小试牛刀 hello-vue3.html <body><div id"app"><h1>{{msg}}</h1></div><script type"module">import {createApp} from https://unpkg.com/vue3/dist/vue.esm-b…

超强的AI写简历软件

你们在制作简历时&#xff0c;是不是基本只关注两件事&#xff1a;简历模板&#xff0c;还有基本信息的填写。 当你再次坐下来更新你的简历时&#xff0c;可能会发现自己不自觉地选择了那个“看起来最好看的模板”&#xff0c;填写基本信息&#xff0c;却没有深入思考如何使简历…

Opencv——图片卷积

图像滤波是尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。 线性滤波是图像处理最基本的方法,它允许我们对图像进行处理,产生很多不同的效果。首先,我们需要一个二…

颠覆传统楼宇管理,拥抱城市美好生活

智慧楼宇是指通过智能化技术和设备&#xff0c;对楼宇的设施、环境和应用进行全面感知、连接和优化&#xff0c;实现楼宇的智能化、高效化和安全化的建筑。智慧楼宇具有全面感知、实时监控、智能控制、优化管理、节能环保等特点&#xff0c;可以为建筑提供更高效、更便捷、更安…

V90伺服PN总线绝对值编码器点动模式往复运动控制实验(SCL代码)

V90伺服驱动器其它相关介绍,请参考V90控制专栏,常用地址如下: V90 Epos模式下点动控制 https://rxxw-control.blog.csdn.net/article/details/134263795https://rxxw-control.blog.csdn.net/article/details/134263795绝对定位往复运动可以参考下面文章链接: https://rx…

【数据结构 06】二叉树

一、原理 二叉树算法核心思维&#xff1a;递归 满二叉树&#xff1a;二叉树的层数为K&#xff0c;节点数为 完全二叉树&#xff1a;二叉树的层数为K&#xff0c;前K-1层是满的&#xff0c;第K层是连续的 满二叉树是完全二叉树的子集。 任意二叉树&#xff1a;若叶子节点的…

CRF条件随机场学习记录

阅读建议 仔细阅读书[1]对应的序列标注章节&#xff0c;理解该方法面向的问题以及相关背景&#xff0c;然后理解基础的概念。 引言 威胁情报挖掘的相关论文中&#xff0c;均涉及到两部分任务&#xff1a;命名实体识别&#xff08;Named Entity Recognition&#xff0c;NER&a…

android学习笔记----ListView和各种适配器简介

打气筒&#xff08;LayoutInflater对象&#xff09;介绍&#xff1a; MainActivity.java import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import an…

Springboot 实现基于用户和物品的协同过滤算法

目录 简介 协同过滤算法(简称CF) 算法详解 算法使用 基于用户 基于物品 总结 前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&#xff0c;我们往往容易陷入工作的漩涡&#xff0c;忘记了停…

对作用域链的理解(详细解析)

文章目录 一、作用域全局作用域函数作用域块级作用域 二、词法作用域三、作用域链 一、作用域 作用域&#xff0c;即变量&#xff08;变量作用域又称上下文&#xff09;和函数生效&#xff08;能被访问&#xff09;的区域或集合 换句话说&#xff0c;作用域决定了代码区块中变…

腾讯云部署vue+node项目

文章目录 一、安装宝塔二、vue项目部署三、node项目部署 前言: 关于项目部署,一开始也是找了很多资料,费了点时间,所以记录一下。希望能对各位有所帮助。 一、安装宝塔 1.首先在控制台,进入云服务器的终端界面 2.输入命令和密码获取权限,并且安装宝塔界面 yum install -y w…

腾讯云0基础10秒搭建幻兽帕鲁游戏联机服务器

幻兽帕鲁&#xff08;Palworld&#xff09;是一款多人在线游戏&#xff0c;为了获得更好的游戏体验&#xff0c;需要搭建一个稳定、高效的游戏联机服务器。腾讯云提供了一种简单、快速的方法&#xff0c;让新手小白也能0基础10秒搭建幻兽帕鲁游戏联机服务器&#xff01; 本文将…

计算机网络_1.2因特网概述

1.2因特网概述 一、网络、互联网与因特网的区别与联系1、网络2、互联网3、因特网4、 互联网与因特网辨析 二、因特网介绍1、因特网发展的三个阶段2、因特网简介&#xff08;1&#xff09;因特网服务提供者&#xff08;ISP&#xff09;&#xff08;2&#xff09;因特网已经发展成…

基于Springboot的视频网站系统的设计与实现(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的视频网站系统的设计与实现&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层…

ESP8266 传感器搭配 Node-RED实时显示数据,邮件告警 实验

前言 esp8266 12f,wif模块,接倾斜传感器,火焰传感器,烟雾传感器,水浸传感器,蜂鸣器。通过mqtt发布数据,并使用node-red实时获取数据,显示到页面上。并且通过邮件和页面两种方式报警。 需求如下: ①倾斜传感器:监测是否保持平衡。UI界面显示平衡度。如果不平衡,UI界…

Observability:在 Elastic Stack 8.12 中使用 Elastic Agent 性能预设

作者&#xff1a;来自 Elastic Nima Rezainia, Bill Easton 8.12 中 Elastic Agent 性能有了重大改进 最新版本 8.12 标志着 Elastic Agent 和 Beats 调整方面的重大转变。 在此更新中&#xff0c;Elastic 引入了 Performance Presets&#xff0c;旨在简化用户的调整过程并增强…

上位机图像处理和嵌入式模块部署(视频处理vs图像处理)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 从目前发展的情况来看&#xff0c;视频处理会慢慢变成一种主流趋势。这里面的原因很多&#xff0c;比如说现在嵌入式soc的算力越来越强、获取图像的…

如何从视频中提取高清图片?可以这样截取

如何从视频中提取高清图片&#xff1f;从视频中提取高清图片可以方便我们制作各种用途所需的素材&#xff0c;如海报、社交媒体配图等。此外&#xff0c;高清图片的细节和色彩也更丰富&#xff0c;可以更好地满足我们的视觉需求。从视频中提取高清图片是一项需要技巧的任务&…

Gateway API 实践之(六)FSM Gateway 的健康检查功能

FSM Gateway 流量管理策略系列&#xff1a; 故障注入黑白名单访问控制限速重试会话保持健康检查负载均衡算法TLS 上游双向 TLS 网关的健康检查功能是一种自动化监控机制&#xff0c;用于定期检查和验证后端服务的健康状况&#xff0c;确保流量只被转发到那些健康且能正常处理请…