C++堆详细讲解

news/2024/5/13 11:53:57

介绍

二叉堆是一种基础数据结构,主要应用于求出一组数据中的最大最小值。C++ 的STL中的优先队列就是使用二叉堆。

堆的性质 : 

1 . 堆是一颗完全二叉树 ;

2 . 堆分为大根堆 和 小根堆(这里不讨论那些更高级的如:二叉堆,二叉堆,左偏树等等)

3 . 大根堆满足每个节点的键值都小于等于其父亲键值 ;

4 . 小根堆满足每个结点的键值都大于等于其父亲键值 ;

5 .(小根)堆主要支持的操作有:插入一个数、查询最小值、删除最小值、合并两个堆、减小一个元素的值。

6 . 大根堆和小根堆作用相反 ;

堆的操作 :

1 . 插入

        堆的插入就是把新的元素放到堆底,然后检查它是否符合堆的性质,如果符合就丢在那里了,如果不符合,那就和它的父亲交换一下,一直交换交换交换,直到符合堆的性质,那么就插入完成了 ;

示例 : 

例如下图要插入一个0 : 

First :

先将该元素插入末尾 : 

Second : 

与5比较,5>0,那么交换 : 

Third : 

再与2换 : 

fourth :

再与1交换,变成小根堆,插入结束 : 

code : 

typedef long long LL ;
const int N = 1e6 + 10 ;
void swap(int &x ,int &y){int t=x;x=y;y=t;}
int heap[N] ;
int sz ;// 堆的大小// 小根堆的插入 
void push(int x){heap[++sz] = x ;int tmp = sz ;while(tmp){//还没到根节点,继续交换 LL nxt = tmp >> 1 ; // 找到父节点下标if(heap[nxt]>heap[tmp]) swap(heap[nxt],heap[tmp]);//父亲比它大,那么交换else break ;tmp = nxt ; // 交换下标 }return ;
} 

2 . 删除

示例 : 

如果要将0删掉 : 

First : 

在孩子结点中找到一个较小的值进行交换 : (这里和1交换)

Second : 

再与2交换 : 

third : 

再与5交换 : 

fourth : 

最后删掉即可 : 

        在代码实现中是直接把堆顶和堆底交换一下,然后把交换后的堆顶不断与它的子节点交换,直到这个堆重新符合堆性质 : 

code : 

void pop(){ // 删除堆顶swap(heap[sz],heap[1]) ;sz-- ;int now = 1 ;while((now<<1) <= sz){ // 对新栈顶进行向下的交换操作 int nxt = now << 1 ; // 找到左孩子结点下标if(nxt+1<=sz&&heap[nxt+1]<heap[nxt]) nxt ++ ;// 找出与那个孩子交换if(heap[nxt]<heap[now]) swap(heap[now],heap[nxt]);else break ;now = nxt ; // 继续下一层 }	
}

        手写堆支持删除任意元素 , 但是STL中的priority_queue只支持删除堆顶 ;

3 . 查询 : 

直接返回堆顶(获取最大/最小值)即可 ;

堆的STL实现 : 

首先需要引入头文件 : 

#include<queue>

然后定义priority : 

priority_queue<int> q;//这是一个大根堆q
priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q

优先队列的操作 : 

q.top()//取得堆顶元素,并不会弹出
q.pop()//弹出堆顶元素
q.push()//往堆里面插入一个元素
q.empty()//查询堆是否为空,为空则返回1否则返回0
q.size()//查询堆内元素数量

4 . 堆的复杂度

因为堆是一棵完全二叉树,所以对于一个节点数为n的堆,它的高度不会超过log2n

所以对于插入,删除操作复杂度为O(log2n)

查询堆顶操作的复杂度为O(1)

5 . 例题 : 

https://www.luogu.com.cn/problem/P3378

黑匣子 - 洛谷

[NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G - 洛谷

中位数 - 洛谷

[USACO09OPEN] Work Scheduling G - 洛谷

以【模板】堆 - 洛谷 为例 : 

手写堆 : 

#include<bits/stdc++.h>
using namespace std;typedef long long LL ;
const int N = 1e6 + 10 ;
void swap(int &x ,int &y){int t=x;x=y;y=t;}
int heap[N] ;
int sz ;// 堆的大小// 小根堆的插入 
void push(int x){heap[++sz] = x ;int tmp = sz ;while(tmp){//还没到根节点,继续交换 LL nxt = tmp >> 1 ; // 找到父节点下标if(heap[nxt]>heap[tmp]) swap(heap[nxt],heap[tmp]);//父亲比它大,那么交换else break ;tmp = nxt ; // 交换下标 }return ;
} void pop(){ // 删除堆顶swap(heap[sz],heap[1]) ;sz-- ;int now = 1 ;while((now<<1) <= sz){ // 对新栈顶进行向下的交换操作 int nxt = now << 1 ; // 找到左孩子结点下标if(nxt+1<=sz&&heap[nxt+1]<heap[nxt]) nxt ++ ;// 找出与那个孩子交换if(heap[nxt]<heap[now]) swap(heap[now],heap[nxt]);else break ;now = nxt ; // 继续下一层 }	
}int main(){int n ; cin >> n ;while(n--){int op ; cin >> op ;if(op==1){int x ; cin >> x ;push(x);}else if(op==2){cout << heap[1] << endl ;}else{pop();}}	
}

使用STL : 

#include<bits/stdc++.h>
using namespace std;int main(){int n ; cin >> n ;priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆qwhile(n--){int op ; cin >> op ;if(op==1){int x ; cin >> x ;q.push(x);}else if(op==2){cout << q.top() << endl ;}else{q.pop();}}	
}


http://www.mrgr.cn/p/07087747

相关文章

论文笔记 SimpleNet A Simple Network for Image Anomaly Detection and Localization

背景 对于工业场景上的异常检测和定位任务, 由于零件的异常情况具有多样性和随机性, 所以很难用有监督的方式来解决; 目前用的最多的是用无监督的方式, 在训练过程中只使用正常样本进行训练, 目前无监督解决异常检测任务的三个趋势是基于重建的方法, 基于合成的方法以及基于嵌入…

【MySQL】3.2MySQL事务和存储引擎

MySQL事务 一、MySQL事物的概念 事务是一种机制&#xff0c;包含了一件事的完整的一个过程 ●事务是一种机制、一个操作序列&#xff0c;包含了一组数据库操作命令&#xff0c;并且把所有的命令作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这一组数据库命令要么…

量化交易软件开发定制的步骤

量化交易软件的定制开发是一个复杂而精细的过程&#xff0c;需要经过一系列步骤来确保最终交付的软件符合客户的需求并具有高度的可靠性和效率。以下是量化交易软件开发定制的主要步骤&#xff1a; 1. 需求分析与规划 在开始开发之前&#xff0c;首先需要与客户深入沟通&…

Meta 推出SceneScript,一种全新的3D场景重建方式

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Java作业练习_第五周子类与继承作业(小白记录,仅供参考)

@目录第一题第二题第三题第四题第五题第六题第七题第八题第九题第十题 第一题 1在Person类中定义的是 Teacher和Manager类的共性内容, 姓名 属性,年龄属性, String name ; int age;方法say(); 2定义Person类的子类Teacher类。可以使用父类Person的姓名和年龄属性,说话的方…

自媒体用ChatGPT批量洗稿软件V5.9环境配置/软件设置教程【汇总】

大家好&#xff0c;我是淘小白~ 首先&#xff0c;感谢大家的支持~~ ChatGPT采集洗稿软件V5.9版本更新&#xff0c;此次版本更新修改增加了一些内容&#xff1a; 1、自定义多条指令&#xff0c;软件自动判断指令条数&#xff0c;进行输入 2、增加谷歌浏览多账号轮询&#xf…

手把手教你做阅读理解题-初中中考阅读理解解题技巧004-A new way of working-一种新型的工作方式

PDF格式公众号回复关键字:ZKYD004阅读理解技巧,在帮助读者有效获取和理解文本信息方面发挥着重要作用,熟练掌握如下6个技巧,可快速突破阅读理解 1 预览文章结构 在开始深入阅读之前,快速浏览文章的标题、段落开头和结尾,可以迅速把握文章的主题、大致内容和结构 标题通常能…

向量法求点在直线上的投影

已知直线上两点a、b和直线外一点p&#xff0c;求p在直线ab上的投影点。 根据《计算几何之 点在直线上的投影 代码模板与证明》一文中所述&#xff0c;p的投影点p’就是a x ⃗ \vec x x &#xff08;直线的点向式&#xff09;&#xff0c;所以我们只要求出 x ⃗ \vec x x 就能…

JAVAEE——线程池

文章目录 线程池的概念什么是线程池&#xff1f; 标准库中的线程池线程池的创建工厂模式工厂模式的用途线程池涉及到的类有哪些Executor接口ExecutorService接口Executors工厂类AbstractExecutorService虚类ThreadPoolExecutor普通类ThreadPoolExecutor内部的实现4个拒绝策略 线…

蚂蚁感冒

一、问题描述 P8611 [蓝桥杯 2014 省 AB] 蚂蚁感冒 二、问题简析 这道题的关键是如何处理蚂蚁掉头的问题。我们可以把蚂蚁掉头看作直接穿了过去。为什么可以这样做?如果两只蚂蚁中有一只感染,则碰头后两只都感染了,不需要区分哪一只。如果两只蚂蚁都没感染,则碰头后仍未感染…

SpringMVC | SpringMVC中的 “文件上传和下载”

目录: 一、文件上传1.1 文件上传“概述”1.2 文件上传“具体配置” :“前端”中配置“文件上传” ( type“file” 满足3个条件 )“后端”中配置“文件上传” ( 配置id为“CommonsMultipartResolver”的bean 配置“文件上传”的“约束条件” 通过“MultipartFile接口”参数接…

SpringMVC | Spring MVC中的“拦截器”

目录: 一、拦截器 &#xff1a;1. 拦截器的 “概述”2. 拦截器的 “定义” (创建“拦截器”对象)3. 拦截器的 “配置” (让“拦截器”对象生效)4. 拦截器的 “执行流程”“单个拦截器”的执行流程“多个拦截器”的执行流程 二、应用案例一实现用户登录权限验证 作者简介 &#…

iMX6ULL-OpenWRT

iMX6ULL-OpenWRT 基于正点原子的imx6ull阿尔法开发板,移植OpenWRT23.05,仅支持SD卡启动。开源工程地址:https://github.com/boxwoodt/imx6ull_openwrt 功能列表:RTL8188J无线EC20 4G联网WEB 升级1、硬件环境 正点原子阿尔法开发板。核心板V1.6,底板V2.2。4G模块使用EC20-C…

虚拟环境装torch与cuda

遇到问题1 在python环境中导入torchvision的时候,出现了以下错误 ImportError: cannot import name PILLOW_VERSION from PIL 问题:Pillow包版本过高。 解决方法:1.卸载新版本 pip uninstall Pillow 2.安装新版本 pip install Pillow==6.2.2 备注:通过conda进行uninstall好…

SQLiteC/C++接口详细介绍sqlite3_stmt类(十三)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍sqlite3_stmt类&#xff08;十二&#xff09; 下一篇&#xff1a; SQLite数据库文件损坏的可能几种情况 51、sqlite3_stmt_scanstatus_reset sqlite3_stmt_scanstatus_reset 函数用于重置指…

Finereport11 类Excel筛选

微信公众号:次世代数据技术 关注可了解更多的教程。问题或建议,请公众号留言或联系本人; 微信号:weibw162 本教程视频讲解可以关注本人B站账号进行观看:weibw162一、需求描述 在使用FIneReport软件开发时,我们希望前台报表展示时可以类似Excel表格筛选那样,在表头进行多选…

Mybatis复习

mybatis最基础的要记的部分用于简化JDBC的操作,直接在mybatis中编写sql,发送给数据库执行,然后返回结果 编写sql有注解和xml文件两种方法 LocalDate类型对应数据表中的date类型 LocalDateTime类型对应数据表中的datetime类型 预编译sql性能高,安全 like拼接时使用concat(%,…

Linux虚拟机不显示ip地址

情况说明:通过资源管理器结束全部以vm开头的进程,重启后不显示IP地址。

C++自主点餐系统

一、 题目 设计一个自助点餐系统&#xff0c;方便顾客自己点餐&#xff0c;并提供对餐厅销售情况的统计和管理功能。 二、 业务流程图 三、 系统功能结构图 四、 类的设计 五、 程序代码与说明 头文件1. SystemMap.h #pragma once #ifndef SYSTEMMAP #define SYSTEMMAP #in…

把项目推送到gitee

好久不用git了,今天就用git上传自己菜鸟项目。上传了模型训练还有模型部署到web的项目。