(堆) 优先队列(堆)的简单实现

文章目录

    • 🏔️堆是什么?
    • 🏔️C++ 标准库
    • 🏔️手动实现
      • ⛰️原理简介
      • ⛰️C++
      • ⛰️C语言
    • ⭐END
      • 🌟交流方式

🏔️堆是什么?

堆简介 - OI Wiki

堆是一棵树,其每个节点都有一个键值,且每个节点的键值都大于等于/小于等于其父亲的键值。

每个节点的键值都大于等于其父亲键值的堆叫做小根堆,否则叫做大根堆。

容器适配器 - OI Wiki

优先队列 std::priority_queue 是一种 堆,一般为 二叉堆。


本文以 1845. 座位预约管理系统 为例进行使用和简单实现的讲解。(本题是小顶堆)

🏔️C++ 标准库

std::priority_queue - cppreference.com

class SeatManager {std::priority_queue<int, vector<int>, greater<int>> heap;public:SeatManager(int n) {for (int i = 1; i <= n; i += 1) {heap.push(i);}}int reserve() {int ret = heap.top();heap.pop();return ret;}void unreserve(int seatNumber) {heap.push(seatNumber);}
};

algorithm 堆操作

class SeatManager {vector<int> heap;public:SeatManager(int n) {for (int i = 1; i <= n; ++i) {heap.push_back(i);}}int reserve() {pop_heap(heap.begin(), heap.end(), greater<int>());int tmp = heap.back();heap.pop_back();return tmp;}void unreserve(int seatNumber) {heap.push_back(seatNumber);push_heap(heap.begin(), heap.end(), greater<int>());}
};

🏔️手动实现

⛰️原理简介

核心:用数组模拟完全二叉树。

在这里插入图片描述

用数组模拟完全二叉树,下标[0, n - 1]节点i的所有子树为left = i * 2 + 1right = i * 2 + 2

两个重要操作,注意不要越界。

堆调整

针对我们要维护的节点fa,对其左右子节left, right点进行比较,找出最值。交换到当前节点fa上。

然后交换后的位置也要同样的维护,因此可以进行迭代或者递归。

// [0, n - 1]
int fa;
int left  = (fa << 1) + 1;
int right = (fa << 1) + 2;
// e.g.
// fa = 0	left = 1	right = 2

尾部新元素维护

因为我们是数组模拟,不是链式的二叉树。因此直接在末尾添加元素比较方便。

而末尾的新元素要和其父元素进行比较。如果要提升,则将父元素复制到子节点。

同理不断直到根部的迭代或则递归。

// [0, n - 1]
int leaf;
int fa = (leaf - 1) / 2;
// e.g.
// leaf = 7		fa = 3
// leaf = 8		fa = 3

⛰️C++

座位预约管理系统 - 提交记录 - 力扣(LeetCode)

namespace lotus {
template <typename T, typename Compare = std::less<T>>
struct Heap {
public:  // Member typesusing value_compare = Compare;using value_type    = T;using size_type     = std::size_t;private:  // Memberstd::vector<value_type> heap;value_compare           cmp;public:  // constructor & distructorHeap()  = default;~Heap() = default;public:  // Element accessvalue_type& top() {return heap[0];}public:  // Capacitybool empty() const {return heap.empty();}size_type size() const {return heap.size();}public:  // Modifiersvoid push(const value_type& value) {heap.push_back(value);// 自底向上进行调整int i = this->size() - 1;for (; i > 0 && cmp(value, heap[(i - 1) >> 1]); i = (i - 1) >> 1) {heap[i] = heap[(i - 1) >> 1];}heap[i] = value;}void pop() {value_type ret = heap.front();heap.front()   = heap.back();heap.pop_back();if (this->size()) {heapify(heap, 0, this->size() - 1);}}public:static void heapify(vector<int>& arr, int fa, int border) {assert(fa <= border);assert((int)arr.size() - 1 <= border);value_compare cmp{};while ((fa << 1) + 1 <= border) {int left  = (fa << 1) + 1;int right = (fa << 1) + 2;int idx   = fa;if (left <= border && cmp(arr[left], arr[idx])) {idx = left;}if (right <= border && cmp(arr[right], arr[idx])) {idx = right;}if (idx != fa) {swap(arr[fa], arr[idx]);fa = idx;} else {break;}}  // while loop}
};
}  // namespace lotusclass SeatManager {lotus::Heap<int> heap;// std::priority_queue<int, vector<int>, greater<int>> heap;public:SeatManager(int n) {for (int i = 1; i <= n; i += 1) {heap.push(i);}}int reserve() {int ret = heap.top();heap.pop();return ret;}void unreserve(int seatNumber) {heap.push(seatNumber);}
};/*** Your SeatManager object will be instantiated and called as such:* SeatManager* obj = new SeatManager(n);* int param_1 = obj->reserve();* obj->unreserve(seatNumber);*/

⛰️C语言

座位预约管理系统 - 提交记录 - 力扣(LeetCode)

// [lotus - heap - begin]
typedef size_t size_type;
typedef int    value_type;
typedef bool (*value_compare)(const value_type*, const value_type*);#define M (100000 + 10)bool less(const void* x, const void* y) {return *(value_type*)x < *(value_type*)y;
}void swap(value_type* x, value_type* y) {value_type tmp = *x;*x             = *y;*y             = tmp;
}void heapify(value_type* arr, int fa, int border, value_compare cmp) {assert(fa <= border);while ((fa << 1) + 1 <= border) {int left  = (fa << 1) + 1;int right = (fa << 1) + 2;int idx   = fa;if (left <= border && cmp(&arr[left], &arr[idx])) {idx = left;}if (right <= border && cmp(&arr[right], &arr[idx])) {idx = right;}if (idx != fa) {swap(&arr[fa], &arr[idx]);fa = idx;} else {break;}}  // while loop
}// data struct
typedef struct {size_type     size;value_type    heap[M];value_compare cmp;
} Heap;// constructor & distructor
void heap_constructor(Heap* p) {p->size = 0;p->cmp  = (value_compare)&less;
}void heap_distructor(Heap* p) {free(p);
}// Element access
value_type heap_top(Heap* p) {return p->heap[0];
}// Capacity
bool empty(Heap* p) {return 0 == p->size;
}
size_type size(Heap* p) {return p->size;
}// Modifiers
void heap_push(Heap* p, const value_type value) {p->heap[p->size]  = value;p->size          += 1;// 自底向上进行调整int i             = p->size - 1;for (; i > 0 && p->cmp(&value, &p->heap[(i - 1) >> 1]); i = (i - 1) >> 1) {p->heap[i] = p->heap[(i - 1) >> 1];}p->heap[i] = value;
}void heap_pop(Heap* p) {value_type ret  = p->heap[0];p->heap[0]      = p->heap[p->size - 1];p->size        += -1;if (p->size) {heapify(p->heap, 0, p->size - 1, p->cmp);}
}
// [lotus - heap - end]// [leetcode - Solution - begin]
typedef struct {Heap* heap;
} SeatManager;SeatManager* seatManagerCreate(int n) {SeatManager* p = (SeatManager*)malloc(sizeof(SeatManager));p->heap        = (Heap*)malloc(sizeof(Heap));heap_constructor(p->heap);for (int i = 1; i <= n; i += 1) {heap_push(p->heap, i);}return p;
}int seatManagerReserve(SeatManager* obj) {int ret = heap_top(obj->heap);heap_pop(obj->heap);return ret;
}void seatManagerUnreserve(SeatManager* obj, int seatNumber) {heap_push(obj->heap, seatNumber);
}void seatManagerFree(SeatManager* obj) {heap_distructor(obj->heap);free(obj);
}
// [leetcode - Solution - end]/*** Your SeatManager struct will be instantiated and called as such:* SeatManager* obj = seatManagerCreate(n);* int param_1 = seatManagerReserve(obj);* seatManagerUnreserve(obj, seatNumber);* seatManagerFree(obj);
*/

⭐END

🌟交流方式

关注我,学习更多C/C++,python,算法,软件工程,计算机知识!

⭐交流方式⭐ |C/C++|算法|设计模式|软件架构-CSDN社区

B站

👨‍💻主页:天赐细莲 bilibili

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

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

相关文章

springboot+Loki+Loki4j+Grafana搭建轻量级日志系统

文章目录 前言一、日志组件介绍 1.1 Loki组件1.2 Loki4j组件1.3 Grafana 二、组件下载安装运行 Loki下载安装运行Grafana下载安装运行 三、创建springboot项目总结 前言 日志在任何一个web应用中都是不可忽视的存在&#xff0c;它已经成为大部分系统的标准组成部分。搭建日志…

自然语言处理:从入门到精通全指引

一、引言 自然语言处理&#xff08;NLP&#xff09;作为人工智能领域的关键分支&#xff0c;旨在让计算机理解、生成和处理人类语言&#xff0c;近年来取得了令人瞩目的成就&#xff0c;在智能客服、机器翻译、文本分析、语音助手等众多领域发挥着重要作用。从入门到精通自然语…

opencvocr识别手机摄像头拍摄的指定区域文字,文字符合规则就语音报警

安装python&#xff0c;pycharm&#xff0c;自行安装。 Python下安装OpenCv 2.1 打开cmd,先安装opencv-python pip install opencv-python --user -i https://pypi.tuna.tsinghua.edu.cn/simple2.2 再安装opencv-contrib-python pip install opencv-contrib-python --user …

智能时代网络空间认知安全新观察

文章目录 前言一、历史上的四次认知革命二、人工智能革命掀起认知安全新浪潮三、人工智能技术塑造认知安全新范式四、人工智能治理应对认知安全新思考 前言 12月5日&#xff0c;在2024第三届北外滩网络安全论坛上以“智能时代网络空间认知安全新观察”为主题作主旨演讲&#x…

springboot417社区疫情管理系统-(论文+源码)_kaic

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统社区疫情管理系统信息管理难度大&#xff0c;容错率低&a…

day10性能测试(2)——Jmeter

【没有所谓的运气&#x1f36c;&#xff0c;只有绝对的努力✊】 目录 1、LoadRunner vs Jmeter 1.1 LoadRunner 1.2 Jmeter 1.3 对比小结 2、Jmeter 环境安装 2.1 安装jdk 2.2 安装Jmeter 2.3 小结 3、Jmeter 文件目录结构 4、Jmeter默认配置修改 5、Jmeter元件、组…

可造成敏感信息泄露!Spring Boot之Actuator信息泄露漏洞三种利用方式总结

1.介绍 Spring Boot是一个基于Spring的套件&#xff0c;它提供了一个即开即用的应用程序架构&#xff0c;可以简化Spring应用的创建及部署流程&#xff0c;帮助开发者更轻松快捷地构建出企业及应用。 Spring Boot项目中Actuator模块提供了众多HTTP接口端点&#xff08;Endpoi…

KV Shifting Attention Enhances Language Modeling

基本信息 &#x1f4dd; 原文链接: https://arxiv.org/abs/2411.19574&#x1f465; 作者: Mingyu Xu, Wei Cheng, Bingning Wang, Weipeng Chen&#x1f3f7;️ 关键词: KV shifting attention, induction heads, language modeling&#x1f4da; 分类: 机器学习, 自然语言处…

MongoDB-固定集合(Capped Collection)

在 MongoDB 中&#xff0c;固定集合&#xff08;Capped Collection&#xff09;是一种具有特殊属性的集合。固定集合具有一个固定的最大大小&#xff0c;并且一旦达到该大小时&#xff0c;最早插入的文档将会被自动删除&#xff0c;以便为新的文档腾出空间。固定集合的这种特性…

设计模式——单例模式和工厂模式

单例模式:一个类只创建一个类对象&#xff08;节省内存减少类对象数量,一个类对象多次重复使用&#xff09; 格式: class a: pass ba() z1b z2b #z1和z2为同一个类对象 工厂模式&#xff1a;&#xff08;大批量创建具体的类对象,统一类对象入口便于维护&#xf…

Unity教程(十九)战斗系统 受击反馈

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现 Unity教程&…

从感知到认知:解读人工智能技术的核心突破

引言&#xff1a;感知与认知的人工智能之旅 人工智能的演进历程&#xff0c;就像人类的成长过程&#xff0c;从最初学会“看”“听”“感知”这个世界&#xff0c;到逐渐具备“理解”“推理”和“决策”的能力。这两个阶段——感知与认知&#xff0c;不仅是人工智能的技术核心&…

文生图模型开源之光!ComfyUI - AuraFlow本地部署教程

一、模型介绍 AuraFlow 是唯一一个真正开源的文生图模型&#xff0c;由Fal团队开源&#xff0c;其代码和权重都放在了 FOSS 许可证下。基于 6.8B 参数优化模型架构&#xff0c;采用最大更新参数化技术&#xff0c;还重新标注数据集提升指令遵循质量。在物体空间和色彩上有优势…

SpringMVC ——(1)

1.SpringMVC请求流程 1.1 SpringMVC请求处理流程分析 Spring MVC框架也是⼀个基于请求驱动的Web框架&#xff0c;并且使⽤了前端控制器模式&#xff08;是⽤来提供⼀个集中的请求处理机制&#xff0c;所有的请求都将由⼀个单⼀的处理程序处理来进⾏设计&#xff0c;再根据请求…

Docker 安装 中文版 GitLab

Docker 安装系列 安装GitLab、解决服务器内存不足问题、使用域名/IP地址访问项目 1、拉取 [rootTseng ~]# docker pull twang2218/gitlab-ce-zh:latest latest: Pulling from twang2218/gitlab-ce-zh 8ee29e426c26: Pull complete 6e83b260b73b: Pull complete e26b65fd11…

python基于基于自然语言处理技术的话题文本分类

大家好我是君君学姐&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款《python基于基于自然语言处理技术的话题文本分类》毕业设计项目。项目源码以及部署相关请联系君君学姐&#xff0c;文末附上联系信息 。 &#x1f388;作者&#xff1a;君君学姐&#x1f388; …

Scala的正则表达式二

验证用户名是否合法 规则 1.长度在6-12之间 2.不能数字开头 3.只能包含数字&#xff0c;大小写字母&#xff0c;下划线def main(args: Array[String]): Unit {val name1 "1admin"//不合法&#xff0c;是数字开头val name2 "admin123"//合法val name3 &quo…

mysql高级篇 | 尚硅谷 | 第11章_数据库的设计规范

十一、数据库的设计规范 文章目录 十一、数据库的设计规范一、为什么需要数据库设计二、范式1、范式简介2、范式都包括哪些3、键和相关属性的概念4、第一范式(1st NF)5、第二范式(2nd NF)6、第三范式(3rd NF)7.小结 三、反范式化1、概述2、应用举例3、反范式的新问题4、反范式的…

【汽车】-- 发动机类型

汽车发动机根据不同的分类标准可以分为多种类型。以下是常见的发动机类型及其特点&#xff0c;并列举相应的品牌和车型举例&#xff1a; 1. 按燃料类型分类 (1) 汽油发动机 特点&#xff1a;使用汽油作为燃料&#xff0c;通过火花塞点火&#xff0c;转速高&#xff0c;运转平…

【蓝桥杯每日一题】砍竹子

砍竹子 2024-12-7 蓝桥杯每日一题 砍竹子 STL 贪心 题目大意 这天, 小明在砍竹子, 他面前有 nn 棵竹子排成一排, 一开始第 ii 棵竹子的 高度为 h i h_i hi​. 他觉得一棵一棵砍太慢了, 决定使用魔法来砍竹子。魔法可以对连续的一 段相同高度的竹子使用, 假设这一段竹子的高度为…