例说数据结构&STL(六)——heap

2023-10-29

1 白话队列(queue)
  heap并不归属于STL容器组件,不像队列queue它们拥有自己独立的类定义,它只能借助其他诸如数组,vector等数据结构完成堆的构造操作。但是heap实际当中有很重要的应用,像大家最熟悉的堆排序,所以STL中还是有对应的函数定义的。
  接触过堆排序的知道,所谓binary heap 就是一种complete binary tree(完全二叉树),也就是说,整棵binary tree 除了最底层的叶节点之外,是填满的,而最底层的叶节点(s)由左至右又不得有空隙。如下图所示:

这里写图片描述

  将像上图一样,我们还是借助例如数组存储完全二叉树的信息,当完全二叉树中的某个节点位于数组的i处时,其左子节点必位于数组的2i处,其右子节点比位于数组的2i+1处,其父节点必位于“i/2”处。通过这么简单的位置规则,数组可以轻易实现出完全二叉树。
  根据元素的排列方式,heap可分为最大堆(max-heap )和 最小堆(min-heap)两种,前者每个节点的键值都大于或等于其子节点键值,后者的每个节点键值都小于或等于其子节点键值。STL默认提供的是最大堆。
2 STL中heap实战
 2.1 包含heap的头文件
  heap构建,排序,删除元素等函数操作是定义在algorithm头文件中的,其实这个头文件中还包含STL很多其他非常优秀的算法,感兴趣的可以查阅相关资料自行学习,它可以让你的编程事半功倍。另外一直强调的std命名空间,实现如下:

#include<algorithm>

using namespace std;

 2.2 构建堆
  前面说过堆的构建需要借助一个载体,本文中我们围绕vector容器来搭建与处理堆。首先我们来看看堆的构建:

int nArr[10] = {0,2,8,9,1,4,3,7,5,6};
vector<int> vec(nArr,nArr+10);    //构建载体vector

make_heap(vec.begin(),vec.end()); //围绕vec构建一个堆。

  上面vector初始化的时候保存数据顺序是0,2,8,9,1,4,3,7,5,6,经过堆构建处理最后vector中数据的顺序变成9,7,8,5,6,4,3,2,0,1。新的vector中的数据是完全符合堆的规则的,即前者每个节点的键值都大于或等于其子节点键值,后者的每个节点键值都小于或等于其子节点键值。
 2.3 出堆操作
  此处出堆操作就是指删除堆中根节点。下图是 pop_heap算法的实际操演情况。既然身为max-heap,最大值必然在根节点。pop操作取走根节点(其实是设至底部容器vector的尾端节点)后,为了满足完全二叉树的条件,必须割舍最下层最右边的叶节点,并将其值重新安插至max-heap(因此有必要重新调整heap结构)。

这里写图片描述

  这里需要注意的是对vector出堆操作必须保证vector中数据是堆存储的,也就是出堆之前一定要make_heap()操作。此外出堆之后,并不是vector中最大值被删除,而是暂且保存到vector中最后一位,也就是说真正删除该数还必须在vector中删除依次。程序如下:

pop_heap(vec.begin(),vec.end()); // 出堆根节点,将其暂存vector最后一位

vec.pop_back(); // vector删除出堆的数据,即最后一位,现在是8,7,4,5,6,1,3,2,0

 2.4 入堆操作
  和出堆正好相反,入堆是先将数放置在堆叶节点,并且是由左向右第一个空叶节点,时刻保证是完全二叉树的原则,然后依次上溯。上溯就是将新节点拿来与其父节点比较,如果其键值(key)比父节点大,就父子对换位置。如此一直上溯,直到不需对换或直到根节点为止。过程如下:

这里写图片描述

  需要注意在入堆之前,一定要保证vector尾部已经插入一个新的数,而且和出堆一样,操作之前一定要保证vector已经建堆。程序如下:

vec.push_back(50); // 先添加一个新数据

push_heap(vec.begin(),vec.end()); //再入堆操作

 2.5 堆排序操作
  堆排序操作的前提也是一样,需要构建堆,然后我们就可以进行堆排序让vector中的数是顺序排列的,通过上面的操作最后的顺序就是0,1,2,3,4,5,6,7,8,50。记住是增序。

sort_heap(vec.begin(),vec.end()); //堆排序

  这块解释一下为什么是增序,实际上上面的排序实现就是依靠依次出堆的操作完成的,我们已经知道出堆都会将默认大根节点保存在vector的末尾,所以最终所有的数据就依次在vector中是增序排列的。
3 小结
  上面详细的介绍了heap数据结构以及STL中提供的几个与堆有关的方法接口。由于heap的所有元素都必须遵循完全二叉树的排列规则,所以heap不提供遍历功能,也不提供迭代器。
  以上是个人学习记录,由于能力和时间有限,如果有错误望读者纠正,谢谢!
  转载请注明出处:http://blog.csdn.net/FX677588/article/details/76358777


  参考博文:
  http://www.cnblogs.com/yyxt/p/4979681.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

例说数据结构&STL(六)——heap 的相关文章

  • 我的博客之分界线

    从正式学习C 到秋招差不多半年的时间 博客完全地记录了我的学习路线以及穿插其中的一些小情绪 必须承认的是 这段时间的学习主要还是以找工作为目的 昨天提示有新访客的评论 忽然有点被敲打到 找工作是一定会有结束的时候的 但是学习这件事是没有的

随机推荐

  • scanf函数格式化输入

    格式字符说明 a A 读入一个浮点值 仅C99有效 c 读入一个字符 d 读入十进制整数 i 读入十进制 八进制 十六进制整数 o 读入八进制整数 x X 读入十六进制整数 c 读入一个字符 s 读入一个字符串 遇空格 制表符或换行符结束
  • 使用mouse without borders无界键盘鼠标工具实现一套键盘鼠标控制两台电脑(非常的奈斯)

    由于两台电脑 所以就需要搭配两套键盘鼠标 对于有限的办公桌面来说 显得杂乱和拥挤 对于这种情况 微软车库里有这么一个比较方便好用的工具微软无界鼠标 Mouse without Borders 应该注意的一些问题 自己电脑的名字一定要是英文名
  • OpenGL课程设计 光线追踪

    链接 https pan baidu com s 1cBTTbbzRCVBCX H4jf6qMA 提取码 kj8w 一 实验内容与要求 1 1 实验内容 1 实验描述 基于C 也可选择其它编程语言 但需要在实现中体现面向对象的思想 实现完整
  • [HNOI2012]永无乡【splay】

    题目链接 好题哇 学会了什么叫做splay树的合并 这道题很容易会去想到使用并查集来解 当然 我之前写过并查集加上线段树合并来做这道题的 现在换种想法 也是学了splay不久的缘故 写起来磕磕碰碰的 这道题让我也更加的懂了关于splay的根
  • 基于自注意力的生成对抗归因网络的交通流缺失数据修复

    文章信息 Missing Data Repairs for Traffic Flow With Self Attention Generative Adversarial Imputation Net 是2022年7月发表在期刊IEEE T
  • 解决ubuntu20.04网络图标消失,连不上网问题

    Ubuntu20 04虚拟机出现无法上网 此时右上角没有网络标志 Settings gt NetWork也只有VPN一项 打开终端 进行以下操作 sudo service network manager stop sudo rm var l
  • sklearn入门&决策树在sklearn中的实现

    sklearn入门 scikit learn官网 http scikit learn org stable index html 中文翻译网址 https sklearn apachecn org docs master 2 html 算法
  • 基于微信小程序的生活日用品交易平台

    基于微信小程序的生活日用品交易平台 付源码 论文 技术架构 微信小程序 微信小程序 是一种普及型高 新型的 不需要安装就可以使用的程序 它通过搜索栏或者是扫描微信二维码 就可以使用户体验到其功能 申请微信小程序的门槛很低 各行各业的用户与组
  • 硬件设计——电源防反接电路

    电源防反接电路 一 二极管防反接电路 一 案例一 二 案例二 三 防反接二极管三个重要选型参数 二 PMOS防反接电路 一 案例一 二 案例二 三 防反接PMOS管四个重要选型参数 一 二极管防反接电路 一 案例一 原理图 器件分析 二 案
  • IP子网的划分

    文章目录 一 子网掩码 1 产生背景 2 定义 3 分类 二 VLSM算法 1 得出下列参数 2 计算划分结果 3 举例子计算 三 常见子网划分对应关系 四 练习 IP编址 题目 需求 解题 1 192 168 1 100 28 2 172
  • java将图片存储在数据库(mysql)

    今天在做项目的时候遇到一个问题 将图片存储在数据库中 由于数据库中不能直接存储图片类型文件 所以只能转为二进制存储 具体实现如下 数据库处理 将字段类型设置为bolb类型 java处理 public void tt1 图片地址 String
  • 进程的地址空间概述

    前言 每台计算机都有一些主存用来保存正在执行的程序 在一个非常简单的操作系统中 仅仅有一个应用程序运行在内存中 第二个应用程序必须等待 为了运行第二个应用程序 需要把第一个应用程序移除才能把第二个程序装入内存 这种频繁的装入内存的操作是很没
  • WireShark是什么?其作用有哪些?

    当下可使用的抓包工具有很多 其中最为常见的抓包工具就是WireShark wireshark是非常流行的网络封包分析软件 功能十分强大 可以截取各种网络封包 显示网络封包的详细信息 而且它是开源软件 可以放心使用 那么WireShark是什
  • vscode中使用xDebug调试php

    环境 vscode phpstudy8 1 1 3 php7 3 4nts 第一步 安装php扩展 phpstudy中 php设置 扩展组件 XDebug调试组件 选择profile输出 端口监听9000 后面的配置中这个端口要保持一致 第
  • Android 端口号使用

    android 应用程序在启动的时候会被默认分配一个端口号吗 不会 在 Android 中 应用程序通常不会被分配一个默认端口号 如果应用程序需要监听网络连接 则必须明确指定要使用的端口号 怎么指定端口号呢 端口号的分类有哪些 在 Andr
  • Vue拿来直接用的静态登录注册页面、后台主页代码

    一 登录 注册页面 1 静态展示 2 登录 注册静态源码 前提是已经在main js中配置好Element ui的全局使用 npm install element ui S 引入ElementUI import ElementUI from
  • 谐振电路的工作原理是什么?以及应用,麻烦说的详细点

    在具有电阻R 电感L和电容C元件的交流电路中 电路两端的电压与其中电流位相一般是不同的 如果我们调节电路元件 L或C 的参数或电源频率 可以使它们位相相同 整个电路呈现为纯电阻性 电路达到这种状态称之为谐振 在谐振状态下 电路的总阻抗达到极
  • java串行程序转化成并行执行

    在程序开发过程当中 往往存在这样一种情况 程序首先执行完method1得到结果result1之后 在执行method2获得结果result2 然后再按照result1和result2的结果来判定程序下一步的执行 在这里method1和met
  • 发送http请求,获取返回的zip包并读取包内的文件

    需要引入jar包 httpclient httpmime httpcore javax servlet api import javax servlet http HttpServletResponse import java io Fil
  • 例说数据结构&STL(六)——heap

    1 白话队列 queue heap并不归属于STL容器组件 不像队列queue它们拥有自己独立的类定义 它只能借助其他诸如数组 vector等数据结构完成堆的构造操作 但是heap实际当中有很重要的应用 像大家最熟悉的堆排序 所以STL中还