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 来创建和维护堆的使用介绍:

  1. 包含头文件

    #include <queue>
  2. 创建优先队列

    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 来创建一个最小堆。
  3. 插入元素

    使用 push 方法将元素插入堆中,堆会自动维护其性质。

    maxHeap.push(10);
    minHeap.push(5);
  4. 访问堆顶元素

    使用 top 方法可以访问堆顶元素,即最大值(最大堆)或最小值(最小堆)。

    int max = maxHeap.top();
    int min = minHeap.top();
  5. 移除堆顶元素

    使用 pop 方法可以移除堆顶元素,堆会自动维护其性质

    maxHeap.pop(); // 移除最大堆顶元素
    minHeap.pop(); // 移除最小堆顶元素
  6. 检查堆是否为空

    使用 empty 方法可以检查堆是否为空。

    bool isMaxHeapEmpty = maxHeap.empty();
    bool isMinHeapEmpty = minHeap.empty();
  7. 获取堆中元素的数量

    使用 size 方法可以获取堆中元素的数量。

    int maxHeapSize = maxHeap.size();
    int minHeapSize = minHeap.size();
  8. 自定义比较函数

    如果你需要自定义比较函数来定义元素之间的比较规则,可以在创建优先队列时提供自定义比较函数。

    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_heappush_heappop_heapsort_heap 是用于操作堆的四个标准库算法。这些算法用于处理堆数据结构,它们可以帮助你创建、维护和排序堆。以下是它们的用途和用法:

3.2 具体函数

  1. make_heap:([]中内容可省略)

    • 用途:make_heap 用于将一个范围内的元素转化为一个堆,默认是大顶堆(通常是最大堆或最小堆)。
    • 语法:make_heap(first, last,[less<>()/greater<>()]):([]中内容可省略)),其中 firstlast 分别是范围的起始迭代器和结束迭代器。

      其中第三个参数是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
  2. push_heap

    • 用途:push_heap 用于将新元素添加到堆中,同时维护堆的性质。(确保已有的元素序列是一个有效的堆,否则请先使用make_heap创建堆)
    • 语法:push_heap(first, last,[less<>()/greater<>()]),其中 firstlast 定义了一个范围,范围内的元素是一个堆,且在 firstlast - 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(插入新元素后)
  3. pop_heap

    • 用途:pop_heap 用于将(确保已有的元素序列是一个有效的堆,否则请先使用make_heap创建堆)的根节点(通常是最大值或最小值)取出,并将其放在范围的末尾,然后维护剩余元素的堆性质(对前n - 1个元素调用make_heap()函数)。
    • 语法:pop_heap(first, last,[less<>()/greater<>()]),其中 firstlast 定义了一个范围,范围内的元素是一个堆。第三个参数同上
    • 示例:
    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只是移到了最后,并没有去除)
  4. sort_heap

    • 用途:sort_heap 用于对一个(确保已有的元素序列是一个有效的堆,否则请先使用make_heap创建堆)进行排序,将堆中的所有元素按升序排列(小根堆)。
    • 语法:sort_heap(first, last,,[less<>()/greater<>()]),其中 firstlast 定义了一个范围,范围内的元素是一个堆。第三个参数同上。
    • 示例:
    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++ 语法结构--堆的更多相关文章

  1. Linux程序存储结构与进程结构堆和栈的区别【转】

    转自:http://www.hongkevip.com/caozuoxitong/Unix_Linux/24581.html 红客VIP(http://www.hongkevip.com):Linux ...

  2. 04 Linux 指令语法结构与帮助命令

    一.Linux指令语法结构 [tyang3@localhost Desktop]$ command [-options] [arguments] 指令           选项           参 ...

  3. CSS_简介/语法结构/长度单位/应用方式/标签的样式重置/表单样式重置

    一.CSS简介:  w3c(World Wide Web Consortium):万维网联盟,是规定网页标准的一个组织(叫做Web标准) Web标准:是由w3c和其他标准化组织制定的一系列标准的集合, ...

  4. PHP读书笔记(1)-PHP语法结构与变量

    一 .php基础语法 1.php语法结构 标准风格:<?php code; ?>.PHP每句代码用;(分号)结尾.<---就用这个,其他的看看就可以了 短风格:<? code; ...

  5. C#中区别多态、重载、重写的概念和语法结构

    C#中区别多态.重载.重写的概念和语法结构 重写是指重写基类的方法,在基类中的方法必须有修饰符virtual,而在子类的方法中必须指明override. 格式: 基类中: public virtual ...

  6. Java初认识--Java中的语法结构

    Java中的语法结构(程序流程控制) Java的语法结构有四种: 1.顺序结构. 顺序结构很简单,就是按顺序执行,输出就可以了. 2.判断结构. 判断结构的一个代表性的语句是if:if语句有三种格式体 ...

  7. Tcl与Design Compiler (二)——DC综合与Tcl语法结构概述

    1.逻辑综合的概述 synthesis = translation + logic optimization + gate mapping . DC工作流程主要分为这三步 Translation : ...

  8. 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认识 ...

  9. PHP基本的语法结构

    学过C语言的话,上手PHP语言就非常快了,如果你有bash shell的基础,那恭喜你,上手PHP会更快,我们先来了解一下一些比较简单的东西,界定符和注释在PHP中的写法: 一 php文档的语法结构 ...

  10. Shader的基本用法和语法结构

    Shader的基本用法和语法结构 本文提供全流程,中文翻译.Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) 1 Introductio ...

随机推荐

  1. parameterType的用法

    在mybatis映射接口的配置中,有select,insert,update,delete等元素都提到了parameterType的用法,parameterType为输入参数,在配置的时候,配置相应的 ...

  2. 牛客刷Java记录第四天

    第一题,单选题 class Car extends Vehicle { public static void main (String[] args) { new Car(). run(); } pr ...

  3. Asp .Net Core 集成 FluentValidation 强类型验证规则库

    目录 入门程序 安装 案例:登录 验证器 内置验证器 自定义验证器 编写自定义验证器 可重复使用的属性验证器 本地化 DI 自动验证 官网:https://docs.fluentvalidation. ...

  4. JPA复杂查询时间查询分页排序

    JPA复杂查询时间查询分页排序 JPA复杂查询时间查询分页排序,工作上用到,因为项目是jpa,记录.代码囊括了:查询条件+时间范围+分页+排序 其实我也不太想用jpa,但是他也有优点,操作可以兼容多种 ...

  5. 我的第一个JavaWeb程序!!!

  6. 深入了解RC4 Drop加密技术

    一.引言 在网络安全领域,加密技术始终是重中之重.随着计算机技术的发展,加密算法也在不断更新换代.RC4(Rivest Cipher 4)加密算法因其高效.简洁的特性,在信息安全领域得到了广泛的应用. ...

  7. 痞子衡嵌入式:原来i.MXRT1170内部RAM的ECC初始化工作可全部由ROM完成

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT1170内部RAM的ECC初始化工作可全部由ROM完成. 痞子衡之前写了三篇文章 <M7 FlexRAM ECC> ...

  8. 当物联网遇上云原生:K8s向边缘计算渗透中

    摘要:K8s正在向边缘计算渗透,它为边缘侧的应用部署提供了便利性,在一定程度上转变了边缘应用与硬件之间的关系,将两者的耦合度降低. 本文分享自华为云社区<云原生在物联网中的应用[拜托了,物联网! ...

  9. 撬动百亿VRAR产业,让VR们“造”起来

    摘要:四大亮点抢先看,12月28-29日不见不散! 随着5G商用的加速及元宇宙.数字人等概念的兴起,虚拟现实技术作为未来世界的入口,正受到越来越多的关注,也将成为驱动数字经济发展和产业转型升级的关键技 ...

  10. Appuploader工具让ipa上传到App Store 的最新流程和步骤

    ​ 苹果官方提供的工具xcode上架ipa非常复杂麻烦.用appuploader 可以在 mac 和windows 上制作管理 证书 ,无需钥匙串工具 条件:1.以Windows为例,创建app打包i ...