【数据结构】堆(大根堆、小根堆)的C++代码模板

news/2025/3/28 9:03:25/文章来源:https://www.cnblogs.com/Tshaxz/p/18792170

大根堆/最大堆

以下是 大根堆(Heap)的C++代码模板,包含最大堆的基本操作(插入、删除堆顶、堆化等),注释详细说明关键步骤:

class MaxHeap {
private:vector<int> heap;// 获取父节点索引int parent(int i) { return (i - 1) / 2; }// 获取左子节点索引int left(int i) { return 2 * i + 1; }// 获取右子节点索引int right(int i) { return 2 * i + 2; }// 上浮操作:将节点i向上调整,维护堆性质void siftUp(int i) {while (i > 0 && heap[i] > heap[parent(i)]) {swap(heap[i], heap[parent(i)]);i = parent(i);}}// 下沉操作:将节点i向下调整,维护堆性质void siftDown(int i, int n) {int maxIndex = i;int l = left(i), r = right(i);if (l < n && heap[l] > heap[maxIndex]) maxIndex = l;if (r < n && heap[r] > heap[maxIndex])maxIndex = r;if (maxIndex != i) {swap(heap[i], heap[maxIndex]);siftDown(maxIndex, n); // 递归调整}}public:// 构造函数1:通过数组建堆MaxHeap(vector<int>& nums) {heap = nums;// 从最后一个非叶子节点开始调整for (int i = heap.size()/2 - 1; i >= 0; i--) {siftDown(i, heap.size());}}// 构造函数2:空堆MaxHeap() {}// 插入元素void push(int val) {heap.push_back(val);siftUp(heap.size() - 1); // 新元素上浮}// 删除堆顶元素(最大值)void pop() {if (heap.empty()) return;swap(heap[0], heap.back());heap.pop_back();siftDown(0, heap.size()); // 新堆顶下沉}// 获取堆顶元素(最大值)int top() {if (!heap.empty()) return heap[0];throw out_of_range("Heap is empty");}// 判断堆是否为空bool empty() { return heap.empty(); }// 获取堆大小int size() { return heap.size(); }
};

image

使用示例

int main() {// 示例1:通过数组建堆vector<int> arr = {3, 1, 6, 5, 2, 4};MaxHeap maxHeap(arr);while (!maxHeap.empty()) {cout << maxHeap.top() << " "; // 输出:6 5 4 3 2 1 maxHeap.pop();}// 示例2:逐个插入元素MaxHeap heap;heap.push(3);heap.push(1);heap.push(6);heap.push(5);cout << heap.top(); // 输出:6heap.pop();cout << heap.top(); // 输出:5return 0;
}

image

小根堆/最小堆

以下是 小根堆(Min Heap)的C++代码模板,包含插入、删除堆顶、堆化等基本操作,注释详细说明修改关键点:

class MinHeap {
private:vector<int> heap;// 获取父节点索引(与最大堆相同)int parent(int i) { return (i - 1) / 2; }// 获取左子节点索引(与最大堆相同)int left(int i) { return 2 * i + 1; }// 获取右子节点索引(与最大堆相同)int right(int i) { return 2 * i + 2; }// 上浮操作:修改比较符号为 <void siftUp(int i) {while (i > 0 && heap[i] < heap[parent(i)]) { // 仅此处改为 <swap(heap[i], heap[parent(i)]);i = parent(i);}}// 下沉操作:修改比较符号为 <void siftDown(int i, int n) {int minIndex = i;int l = left(i), r = right(i);// 比较子节点中的较小者if (l < n && heap[l] < heap[minIndex])  // 改为 <minIndex = l;if (r < n && heap[r] < heap[minIndex])  // 改为 <minIndex = r;if (minIndex != i) {swap(heap[i], heap[minIndex]);siftDown(minIndex, n); // 递归调整}}public:// 构造函数1:通过数组建堆(调整比较方向)MinHeap(vector<int>& nums) {heap = nums;// 从最后一个非叶子节点开始调整for (int i = heap.size()/2 - 1; i >= 0; i--) {siftDown(i, heap.size());}}// 构造函数2:空堆MinHeap() {}// 插入元素(与最大堆逻辑相同)void push(int val) {heap.push_back(val);siftUp(heap.size() - 1);}// 删除堆顶元素(最小值)void pop() {if (heap.empty()) return;swap(heap[0], heap.back());heap.pop_back();siftDown(0, heap.size());}// 获取堆顶元素(最小值)int top() {if (!heap.empty()) return heap[0];throw out_of_range("Heap is empty");}// 判断堆是否为空bool empty() { return heap.empty(); }// 获取堆大小int size() { return heap.size(); }
};

image

使用示例

int main() {// 示例1:通过数组建堆vector<int> arr = {3, 1, 6, 5, 2, 4};MinHeap minHeap(arr);while (!minHeap.empty()) {cout << minHeap.top() << " "; // 输出:1 2 3 4 5 6 minHeap.pop();}// 示例2:逐个插入元素MinHeap heap;heap.push(3);heap.push(1);heap.push(6);heap.push(5);cout << heap.top(); // 输出:1heap.pop();cout << heap.top(); // 输出:3return 0;
}

image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/905605.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简易聊天室项目(本地部署)

二、IDEA开发 1.创建新的空项目file->project struture->+->new module点击next,选取依赖创建成功后,先将依赖下载(右上角会有一个小的m图标,点击就可以)2.创建文件 先创建三个文件ChatHandler,WebSocketConfig,index.html,位置如下3.粘贴代码,将下面代码粘贴…

20234114 2024-2025-2 《Python程序设计》实验一报告

20234114 2024-2025-2 《Python程序设计》实验一报告 课程:《Python程序设计》 班级: 2341 姓名: 于家欢 学号:20234114 实验教师:王志强 实验日期:2025年3月21日 必修/选修: 公选课 1.实验内容熟悉Python开发环境;练习Python运行、调试技能;编写程序,练习变量和类型…

简易聊天室项目(环境搭建)

从零搭建简易聊天室项目 一.开发环境搭建 1.安装jdk23 访问 Oracle官网 或 OpenJDK镜像站下载,搜索安装教程安装配置 2.安装IDEA 访问 JetBrains官网下载社区版(免费)或旗舰,搜索安装教程安装配置 3.安装MAVEN 可参考b站视频安装 1)下载 访问Maven官网找到自己下载的压缩包…

L2 领导力

Hina...L2 领导力 需求层次 理论 人类受到各种需求的驱动。人是一种追求完全需求的动物。 管理设计对人力资源——我们的同事——的激活,来实现既定的目标,这是通过满足人类的各种需求来操纵人的行为做到的。 马斯洛的需求层次理论指出,一些需求比其他需求更基本,只有在基本…

Crypto类型总结(持续更新)

想做这样的一篇密码学总结的文章的想法主要来自于https://blog.csdn.net/weixin_45728976/article/details/109219997 这篇文章,对于这篇文章里面已经涉及到的内容的基础点不再进行繁琐的讲论。 接下来总结的主要是各种各样的crypto的魔改或者容易忘却的思路 1.unencode加密:…

树链剖分-重链剖分

树链剖分——重链剖分,我学的第一个蓝色算法树链剖分-重链剖分 前置知识 树形结构,链式前向星,线段树,DFS序,LCA 定义 树链剖分(树剖):将树分解为一条条不相交的,从祖先到孙子的链。 第零部分:建树与基本概念 建树:给定\(n\)个节点用链式前向星(或邻接表)建树 基本…

苍穹外卖-day05

redis基本入门 入门略过https://www.bilibili.com/video/BV1TP411v7v6?spm_id_from=333.788.videopod.episodes&vd_source=93f5f50fb9ce34ddae7abba08c6ea064&p=62 50-62级 记了感觉也不会看每次使用redis时需要先启动服务 在redis目录下,进入cmd窗口,输入以下命令启…

2025最新面试题-JVM面试题(二)

堆为什么进行分代设计老年代的担保机制 为什么Eden:S0:S1 是8:1:1 对象的创建以及分配过程方法区与元数据区以及持久代到底是什么关系? Full GC = young GC + Old GC + Meta Space GC 规范:方法区 实现: JDK1.7之前 永久代 持久代 Perm Space 类的总数 常量池大小 方法的…

YashanDB双引号

双引号是对标识符、密码定义和使用的扩展。使用双引号时,标识符、密码定义将支持特殊字符、数字,并且区分字母大小写。 双引号的使用位置(是否可出现在SELECT,FROM和WHERE后)和使用场景规则,以及双引号内字符串的长度限制,由双引号限定的标识符和密码本身决定,与是否加…

YashanDB故障状态

YashanDB检测到异常故障时,防止扩散影响,会将数据库的状态置为ABNORMAL,数据库处于故障只读状态,可以查询,不能执行写的业务。 当数据库为ABNORMAL状态时,可以查看V$DIAG_INCIDENT视图或告警日志明确故障原因。 --故障发生时,数据库状态为ABNORMAL SELECT STATUS FROM V…

YashanDB故障诊断架构

故障诊断架构由多个组件构成,包括自动诊断存储库、运行日志、告警日志等。其中运行日志、告警日志参考日志管理中说明。#自动诊断存储库自动诊断存储库是基于文件的存储库,用于存储数据库的诊断数据。它的目录结构如下(默认放在YASDB_DATA目录下,可设置参数进行配置):其中…