C++ 语法结构--堆
1.堆介绍
「堆 heap」是一种满足特定条件的完全二叉树,主要可分为图 8-1 所示的两种类型。
- 「大顶堆 max heap」:任意节点的值
其子节点的值。 - 「小顶堆 min heap」:任意节点的值
其子节点的值。

堆作为完全二叉树的一个特例,具有以下特性。
最底层节点靠左填充,其他层的节点都被填满。
我们将二叉树的根节点称为“堆顶”,将底层最靠右的节点称为“堆底”。
对于大顶堆(小顶堆),堆顶元素(即根节点)的值分别是最大(最小)的。
2.使用优先级队列(priority_queue)创建和维护堆
2.1 概念
堆(heaps) 是一种特殊的数据组织方式,STL 中的 priority_queue 容器适配器底层就是采用堆来组织数据存储的。
实际上,堆通常用作实现优先队列,大顶堆相当于元素按从大到小顺序出队的优先队列。从使用角度来看,我们可以将“优先队列”和“堆”看作等价的数据结构。因此,这里对两者不做特别区分,统一使用“堆“来命名。
2.2 实例
C++标准库中的 std::priority_queue 是一种用于创建和维护堆的容器适配器。它提供了一种方便的方式来实现堆数据结构,通常用于处理具有优先级的元素。以下是使用 std::priority_queue 来创建和维护堆的使用介绍:
包含头文件:
#include <queue>
创建优先队列:
std::priority_queue<int> maxHeap; // 创建一个最大堆,默认情况下是最大堆
std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap; // 创建一个最小堆
std::priority_queue <int,vector<int>,less<int> > maxHeap;//创建一个最大堆
- 你可以创建一个最大堆(默认情况),或者通过提供第二个参数为
std::vector和第三个参数为std::greater来创建一个最小堆。
- 你可以创建一个最大堆(默认情况),或者通过提供第二个参数为
插入元素:
使用
push方法将元素插入堆中,堆会自动维护其性质。maxHeap.push(10);
minHeap.push(5);
访问堆顶元素:
使用
top方法可以访问堆顶元素,即最大值(最大堆)或最小值(最小堆)。int max = maxHeap.top();
int min = minHeap.top();
移除堆顶元素:
使用
pop方法可以移除堆顶元素,堆会自动维护其性质。maxHeap.pop(); // 移除最大堆顶元素
minHeap.pop(); // 移除最小堆顶元素
检查堆是否为空:
使用
empty方法可以检查堆是否为空。bool isMaxHeapEmpty = maxHeap.empty();
bool isMinHeapEmpty = minHeap.empty();
获取堆中元素的数量:
使用
size方法可以获取堆中元素的数量。int maxHeapSize = maxHeap.size();
int minHeapSize = minHeap.size();
自定义比较函数:
如果你需要自定义比较函数来定义元素之间的比较规则,可以在创建优先队列时提供自定义比较函数。
struct Compare {
bool operator()(int a, int b) {
// 自定义比较规则
return a > b; // 创建最小堆
}
}; std::priority_queue<int, std::vector<int>, Compare> customHeap;
在上述例子中,我们创建了一个自定义的比较函数
Compare,它定义了创建一个最小堆。
std::priority_queue 简化了堆的创建和维护,特别适用于需要按优先级访问元素的问题,如任务调度、Dijkstra算法等。你可以根据问题的要求选择最大堆或最小堆,并通过提供自定义比较函数来实现更复杂的比较规则。
3.使用make_heap等系列函数创建和维护堆
3.1 概念
在C++中,make_heap、push_heap、pop_heap 和 sort_heap 是用于操作堆的四个标准库算法。这些算法用于处理堆数据结构,它们可以帮助你创建、维护和排序堆。以下是它们的用途和用法:
3.2 具体函数
make_heap:([]中内容可省略)- 用途:
make_heap用于将一个范围内的元素转化为一个堆,默认是大顶堆(通常是最大堆或最小堆)。 - 语法:
make_heap(first, last,[less<>()/greater<>()]):([]中内容可省略)),其中first和last分别是范围的起始迭代器和结束迭代器。
其中第三个参数是less<>()或是greater<>(),前者用于生成大顶堆,后者用于生成小顶堆,第三个参数默认情况下为less<>(),less()用于生成大顶堆。 - 示例:
vector<int> nums = {3, 1, 4, 1, 5, 9, 2};
display(nums);
make_heap(nums.begin(), nums.end());
display(nums);
// nums 现在是一个最大堆,最大值 9 在根节点
结果:
(原数组)3 1 4 1 5 9 2
(现数组)9 5 4 1 1 3 2
- 用途:
push_heap:- 用途:
push_heap用于将新元素添加到堆中,同时维护堆的性质。(确保已有的元素序列是一个有效的堆,否则请先使用make_heap创建堆) - 语法:
push_heap(first, last,[less<>()/greater<>()]),其中first和last定义了一个范围,范围内的元素是一个堆,且在first到last - 1之间添加了一个新元素。第三个参数同上。 - 示例:
vector<int> nums = {3, 1, 4, 1, 5};
display(nums);
make_heap(nums.begin(), nums.end());
display(nums);
nums.push_back(9);
push_heap(nums.begin(), nums.end());
display(nums);
// nums 现在是一个最大堆,最大值 9 在根节点 结果:
3 1 4 1 5(原先)
5 3 4 1 1(建堆后)
9 3 5 1 1 4(插入新元素后)
- 用途:
pop_heap:- 用途:
pop_heap用于将堆(确保已有的元素序列是一个有效的堆,否则请先使用make_heap创建堆)的根节点(通常是最大值或最小值)取出,并将其放在范围的末尾,然后维护剩余元素的堆性质(对前n - 1个元素调用make_heap()函数)。 - 语法:
pop_heap(first, last,[less<>()/greater<>()]),其中first和last定义了一个范围,范围内的元素是一个堆。第三个参数同上 - 示例:
vector<int> nums = {9, 1, 4, 1, 5};
display(nums);
make_heap(nums.begin(), nums.end());
display(nums);
pop_heap(nums.begin(), nums.end());
display(nums);
// nums 现在是一个最大堆,最大值 9 被移至范围末尾
结果展示:
9 1 4 1 5(原先)
9 5 4 1 1(建堆后)
5 1 4 1 9(移出一个元素出堆,注意这里的9只是移到了最后,并没有去除)
- 用途:
sort_heap:- 用途:
sort_heap用于对一个堆(确保已有的元素序列是一个有效的堆,否则请先使用make_heap创建堆)进行排序,将堆中的所有元素按升序排列(小根堆)。 - 语法:
sort_heap(first, last,,[less<>()/greater<>()]),其中first和last定义了一个范围,范围内的元素是一个堆。第三个参数同上。 - 示例:
vector<int> nums = {9, 1, 4, 1, 5};
display(nums);
make_heap(nums.begin(), nums.end());
display(nums);
sort_heap(nums.begin(), nums.end());
display(nums); 结果展示:
9 1 4 1 5(原先)
9 5 4 1 1(建堆后)
1 1 4 5 9(排序后)
- 用途:
这些堆算法对于处理堆数据结构非常有用,可以在各种算法和数据结构中使用。堆通常用于实现优先队列和解决一些最大值或最小值相关的问题。这些算法可以提高代码的可读性和效率,因为它们是经过精心设计和优化的标准库函数。
4.二者的区别和各自的优势
4.1 优先级队列优势
priority_queue 可以提供堆没有的优势,它可以自动保持元素的顺序;但我们不能打乱 priority_queue的有序状态,因为除了第一个元素,我们无法直接访问它的其他元素。如果需要的是一个优先级队列,这一点非常有用。
4.2 使用 make_heap()优势
从另一方面来说,使用 make_heap() 创建的堆可以提供一些 priority_queue 没有的优势:
1、可以访问堆中的任意元素,而不限于最大的元素,因为元素被存储在一个容器中,就像是我们自己的 vector。这也提供了偶然破坏元素顺序的可能,但是总可以调用 make_heap()来还原堆。
2、可以在任何提供随机访问迭代器的序列容器中创建堆。这些序列容器包括普通数组、string 对象、自定义容器。这意味着无论什么时候需要,都可以用这些序列容器的元素创建堆,必要时,可以反复创建。甚至还可以为元素的子集创建堆。
C++ 语法结构--堆的更多相关文章
- Linux程序存储结构与进程结构堆和栈的区别【转】
转自:http://www.hongkevip.com/caozuoxitong/Unix_Linux/24581.html 红客VIP(http://www.hongkevip.com):Linux ...
- 04 Linux 指令语法结构与帮助命令
一.Linux指令语法结构 [tyang3@localhost Desktop]$ command [-options] [arguments] 指令 选项 参 ...
- CSS_简介/语法结构/长度单位/应用方式/标签的样式重置/表单样式重置
一.CSS简介: w3c(World Wide Web Consortium):万维网联盟,是规定网页标准的一个组织(叫做Web标准) Web标准:是由w3c和其他标准化组织制定的一系列标准的集合, ...
- PHP读书笔记(1)-PHP语法结构与变量
一 .php基础语法 1.php语法结构 标准风格:<?php code; ?>.PHP每句代码用;(分号)结尾.<---就用这个,其他的看看就可以了 短风格:<? code; ...
- C#中区别多态、重载、重写的概念和语法结构
C#中区别多态.重载.重写的概念和语法结构 重写是指重写基类的方法,在基类中的方法必须有修饰符virtual,而在子类的方法中必须指明override. 格式: 基类中: public virtual ...
- Java初认识--Java中的语法结构
Java中的语法结构(程序流程控制) Java的语法结构有四种: 1.顺序结构. 顺序结构很简单,就是按顺序执行,输出就可以了. 2.判断结构. 判断结构的一个代表性的语句是if:if语句有三种格式体 ...
- Tcl与Design Compiler (二)——DC综合与Tcl语法结构概述
1.逻辑综合的概述 synthesis = translation + logic optimization + gate mapping . DC工作流程主要分为这三步 Translation : ...
- html dl dt dd标签元素语法结构与使用
dl dt dd认识及dl dt dd使用方法 标签用于定义列表类型标签. dl dt dd目录 dl dt dd介绍 结构语法 dl dt dd案例 dl dt dd总结 一.dl dt dd认识 ...
- PHP基本的语法结构
学过C语言的话,上手PHP语言就非常快了,如果你有bash shell的基础,那恭喜你,上手PHP会更快,我们先来了解一下一些比较简单的东西,界定符和注释在PHP中的写法: 一 php文档的语法结构 ...
- Shader的基本用法和语法结构
Shader的基本用法和语法结构 本文提供全流程,中文翻译.Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) 1 Introductio ...
随机推荐
- 华企盾DSC控制台操作卡顿如何解决
解决方法: 修改注册表: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows 的 USERProcessHa ...
- 华企盾DSC发送白名单提示“解密发送失败”(被中转服务器判定为垃圾邮箱)
解决方法:用DebugView监控,发现含有550错误,说明中转服务器被判定为垃圾邮箱,换一个中转邮箱或者设置为无中转发送 还有一种可能:邮箱设置了收到邮箱后自动删除 DebugView中显示上图 ...
- NetSuite 开发日记 —— 估价单(Estimate)新建项目(Project)自动填入项目字段
Background 用户在估价单(Estimate)点击「项目」字段旁边+按钮新建项目(Project),在项目的自定义字段中自动填入估价单ID 用户在项目记录存在切换自定义表格行为 Analysi ...
- CSS实例-切换开关
在线展示: 矩形开关 .switch { position: relative; display: inline-block; width: 60px; height: 34px } .switch ...
- rime中州韵 输入效果一览 100+增强功能效果
rime是一个定制化程度很高的输入法框架, 我们可以在该框架上搭建适合自己的输入法程序.我们将在专栏 小狼毫 Rime 保姆教程 中完成以下近百种定制化效果的配置与演示.欢迎订阅. 以下为个性化定制的 ...
- 案例展示自定义C函数的实现过程
摘要:用户在使用数据库过程中,受限于内置函数的功能,部分业务不易实现时,可以使用自定义C函数实现特殊功能.本文通过两个示例展示自定义C函数的实现过程. 前言 用户在使用数据库过程中,常常受限于内置函数 ...
- 摆平各类目标检测识别AI应用,有它就够了!
摘要:在计算机视觉领域,CANN最新开源的通用目标检测与识别样例,通过其强大的可定制.可扩展性,为AI开发者们提供了良好编程选择. 本文分享自华为云社区<摆平各类目标检测识别AI应用,有它就够了 ...
- 4种Spring Boot 实现通用 Auth 认证方式
摘要: 文章介绍了 spring-boot 中实现通用 auth 的四种方式,包括传统 AOP.拦截器.参数解析器和过滤器,并提供了对应的实例代码,最后简单总结了下它们的执行顺序. 本文分享自华为云社 ...
- 单日30PB量级!火山引擎ByteHouse云原生的数据导入这么做
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 近期,火山引擎ByteHouse技术专家受邀参加DataFunCon2023(深圳站)活动,并以"火 ...
- Rocketmq学习2——Rocketmq消息过滤&事务消息&延迟消息原理源码浅析
系列文章目录和关于我 零丶引入 在<Rocketmq学习1--Rocketmq架构&消息存储&刷盘机制>中我们学习了rocketmq的架构,以及消息存储设计,在此消息存储设 ...