首页 > 编程语言 >C++ 语法结构--堆

C++ 语法结构--堆

时间:2023-10-28 11:44:33浏览次数:30  
标签:priority nums -- 创建 元素 C++ 语法结构 queue heap

1.堆介绍

「堆 heap」是一种满足特定条件的完全二叉树,主要可分为图 8-1 所示的两种类型。

  • 「大顶堆 max heap」:任意节点的值
    其子节点的值。
  • 「小顶堆 min heap」:任意节点的值
    其子节点的值。

image

堆作为完全二叉树的一个特例,具有以下特性。

最底层节点靠左填充,其他层的节点都被填满。
我们将二叉树的根节点称为“堆顶”,将底层最靠右的节点称为“堆底”。
对于大顶堆(小顶堆),堆顶元素(即根节点)的值分别是最大(最小)的。

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),其中 firstlast 分别是范围的起始迭代器和结束迭代器。
    • 示例:
      vector<int> nums = {3, 1, 4, 1, 5, 9, 2};
      make_heap(nums.begin(), nums.end());
      // nums 现在是一个最大堆,最大值 9 在根节点
      
  2. push_heap

    • 用途:push_heap 用于将新元素添加到堆中,同时维护堆的性质。
    • 语法:push_heap(first, last),其中 firstlast 定义了一个范围,范围内的元素是一个堆,且在 firstlast - 1 之间添加了一个新元素。
    • 示例:
      vector<int> nums = {3, 1, 4, 1, 5};
      nums.push_back(9);
      push_heap(nums.begin(), nums.end());
      // nums 现在是一个最大堆,最大值 9 在根节点
      
  3. pop_heap

    • 用途:pop_heap 用于将堆的根节点(通常是最大值或最小值)取出,并将其放在范围的末尾,然后维护剩余元素的堆性质。
    • 语法:pop_heap(first, last),其中 firstlast 定义了一个范围,范围内的元素是一个堆。
    • 示例:
      vector<int> nums = {9, 1, 4, 1, 5};
      pop_heap(nums.begin(), nums.end());
      // nums 现在是一个最大堆,最大值 9 被移至范围末尾
      
  4. sort_heap

    • 用途:sort_heap 用于对一个堆进行排序,将堆中的所有元素按升序排列。
    • 语法:sort_heap(first, last),其中 firstlast 定义了一个范围,范围内的元素是一个堆。
    • 示例:
      vector<int> nums = {9, 5, 4, 1, 1};
      sort_heap(nums.begin(), nums.end());
      // nums 现在是按升序排列的序列
      

这些堆算法对于处理堆数据结构非常有用,可以在各种算法和数据结构中使用。堆通常用于实现优先队列和解决一些最大值或最小值相关的问题。这些算法可以提高代码的可读性和效率,因为它们是经过精心设计和优化的标准库函数。

4.二者的区别和各自的优势

4.1 优先级队列优势

priority_queue 可以提供堆没有的优势,它可以自动保持元素的顺序;但我们不能打乱 priority_queue的有序状态,因为除了第一个元素,我们无法直接访问它的其他元素。如果需要的是一个优先级队列,这一点非常有用。

4.2 使用 make_heap()优势

从另一方面来说,使用 make_heap() 创建的堆可以提供一些 priority_queue 没有的优势:
1、可以访问堆中的任意元素,而不限于最大的元素,因为元素被存储在一个容器中,就像是我们自己的 vector。这也提供了偶然破坏元素顺序的可能,但是总可以调用 make_heap()来还原堆。
2、可以在任何提供随机访问迭代器的序列容器中创建堆。这些序列容器包括普通数组、string 对象、自定义容器。这意味着无论什么时候需要,都可以用这些序列容器的元素创建堆,必要时,可以反复创建。甚至还可以为元素的子集创建堆。

标签:priority,nums,--,创建,元素,C++,语法结构,queue,heap
From: https://www.cnblogs.com/trmbh12/p/17793906.html

相关文章

  • CentOS 7.9 Redis 设置开机自启动
    https://blog.csdn.net/aikudexiaohai/article/details/130102729一、背景说明由于安装的redis,不会自动生成systemctl相关的系统命令,每次启动、重启、停止、查看redis状态,不太方便。可以通过如下步骤,创建系统文件,可以通过标准的systemctl命令方便执行redis的相关操作。......
  • Vue.js框架:vue3引入mockjs模拟数据调试
    一、引入依赖1、安装依赖包在终端中使用以下命令:npminstall@types/mockjs--save此处使用了@types进行引入,是因为在.ts文件引用包时,默认必须有类型声明,不能是any。有很多依赖包是用纯JS写的,没有类型声明。因此使用@types作为类型声明的集......
  • 力扣2558.从数量最多的堆取走礼物
    给你一个整数数组 gifts ,表示各堆礼物的数量。每一秒,你需要执行以下操作:选择礼物数量最多的那一堆。如果不止一堆都符合礼物数量最多,从中选择任一堆即可。选中的那一堆留下平方根数量的礼物(向下取整),取走其他的礼物。返回在 k 秒后剩下的礼物数量。 示例1:输入:gifts......
  • P4260 博弈论与概率统计
    传送门description\(T\)次询问,每次给定\(n,m,p\),总共\(n+m\)局游戏,每局A有\(p\)的概率获胜。一局游戏获胜A的得分加1,否则减1,但是如果A在得分为0的情况下输了一局,得分不变。求A赢\(n\)局,输\(m\)局后游戏结束时A的得分的数学期望。\(n,m,T\leq2.5\time......
  • 第六周助教总结
    第六周助教总结1.学习情况综述在这一周大家学习了《计算机科学概论》第二章、第三章以及《C语言程序设计》第二章,并进行了IEEE754浮点数,BASE64编码的练习,还有部分同学进行了罗马数字转阿拉伯数字以及图像处理的一些练习,与此同时,大多数同学都能坚持练习C语言的题目,对大家来说可以......
  • 手撕Vuex-Vuex实现原理分析
    本章节主要围绕着手撕Vuex,那么在手撕之前,先来回顾一下Vuex的基本使用。创建一个Vuex项目,我这里采用vue-cli创建一个项目,然后安装Vuex。vuecreatevuex-demo选择Manuallyselectfeatures。这里只需要,Babel与Vuex。选择2.X版本的Vue:创建package.json:是......
  • 递归查询
    有时候表结构是层级关系的父子结构,要查出所有有的子,可用如下的sql,递归查询,以mysql为例:1、查出父下所有子WITHRECURSIVEproducttypeAS(SELECT'03f9096d-bd5d-11ed-a58a-7af8c5058daf'FinanClass,id,protypeid,typename,typelevelFROMt_base_commontypeWHEREid='0......
  • 【小星星直播互动宝】——第一时间回复用户问题,自动语音回复,实现无人值守直播
    无人直播已成为当下热门的互联网趋势,然而,频繁的语音重复和低频互动行为常常影响用户体验,给主播和观众带来不必要的困扰。为了解决这一问题,我们地推出了【小星星直播互动宝】,一款功能强大的无人直播语音交互软件,配合小星星去重播放器,为您带来全新的直播体验! 目前支持平台:快手......
  • Laravel 配置多环境env文件(转)
    原文:https://learnku.com/articles/566841、前提主要实现方法是自己提供的useEnvironmentPath(),有兴趣的同学可以去研究下.每个公司的要求不一样,有的习惯进行条件编译加载配置文件,有的不需要条件编译,怕安全泄露token等关键信息,手动修改配置信息.像国内小公司基本不怎么......
  • Spartacus lazy loading 模块中的配置管理
    如果在懒加载模块中提供了额外的配置,组合商店前端将其合并到全局应用配置中,以支持现有组件和服务的懒加载场景。在大多数情况下,尤其是当懒加载模块主要提供默认配置时,这种方式都能可靠地工作。然而,如果过度使用,特别是当两个模块为配置的同一部分提供不同的配置时,可能会导致问题。......