【C++篇】排队的艺术:用生活场景讲解优先级队列的实现
文章目录
须知
💬 欢迎讨论:如果你在学习过程中有任何问题或想法,欢迎在评论区留言,我们一起交流学习。你的支持是我继续创作的动力!
👍 点赞、收藏与分享:觉得这篇文章对你有帮助吗?别忘了点赞、收藏并分享给更多的小伙伴哦!你们的支持是我不断进步的动力!
🚀 分享给更多人:如果你觉得这篇文章对你有帮助,欢迎分享给更多对C++感兴趣的朋友,让我们一起进步!
深入理解与实现:C++优先级队列的模拟实现
1. 引言
在算法和数据结构中,优先级队列是一种极其重要的工具,用于按优先级而非插入顺序处理数据。在C++中,std::priority_queue提供了强大的内置支持,但了解其原理和实现有助于我们更灵活地应用这一数据结构。本文将带你从基础概念出发,逐步实现一个C++版本的优先级队列,并解析其核心原理。
2. 什么是优先级队列?
优先级队列是特殊的队列数据结构,其中每个元素都带有一个优先级,队列的处理顺序依据优先级而定,而不是入队顺序。常见特性包括:
- 优先级定义:通常用数值表示,数值越大或越小(取决于实现)表示优先级越高。
- 操作支持:支持插入、删除优先级最高元素。
2.1 现实生活的比喻
在机场登机时,头等舱乘客拥有更高的优先级,会优先登机;在银行排队时,VIP客户的业务会优先处理。优先级队列以数据结构的方式抽象和实现了这些规则。
3. 优先级队列的实现方式
优先级队列的底层通常基于堆结构(Heap)。堆是一种二叉树,分为最大堆和最小堆:
- 最大堆:根节点是最大值,每个子节点的值都小于或等于父节点。
- 最小堆:根节点是最小值,每个子节点的值都大于或等于父节点。
3.1 常见实现方法
- 基于数组或链表:通过手动排序实现,但效率低下。
- 基于二叉堆:常见且高效,插入和删除的时间复杂度为O(log n)。
- C++ STL中的实现:
std::priority_queue利用堆的机制实现优先级队列。
4. 用C++实现优先级队列
接下来,我们将通过代码逐步构建一个优先级队列。
4.1 手动实现优先级队列(基于最大堆)
#include <iostream>
#include <vector>
#include <stdexcept>class PriorityQueue {
private:std::vector<int> heap;void siftUp(int index) {int parent = (index - 1) / 2;if (index > 0 && heap[index] > heap[parent]) {std::swap(heap[index], heap[parent]);siftUp(parent);}}void siftDown(int index) {int left = 2 * index + 1;int right = 2 * index + 2;int largest = index;if (left < heap.size() && heap[left] > heap[largest])largest = left;if (right < heap.size() && heap[right] > heap[largest])largest = right;if (largest != index) {std::swap(heap[index], heap[largest]);siftDown(largest);}}public:void push(int value) {heap.push_back(value);siftUp(heap.size() - 1);}int pop() {if (heap.empty()) {throw std::runtime_error("Priority queue is empty");}int top = heap[0];heap[0] = heap.back();heap.pop_back();if (!heap.empty()) {siftDown(0);}return top;}bool empty() const {return heap.empty();}int top() const {if (heap.empty()) {throw std::runtime_error("Priority queue is empty");}return heap[0];}
};int main() {PriorityQueue pq;pq.push(10);pq.push(20);pq.push(5);std::cout << "Top element: " << pq.top() << std::endl; // 输出 20std::cout << "Popped element: " << pq.pop() << std::endl; // 输出 20std::cout << "Popped element: " << pq.pop() << std::endl; // 输出 10return 0;
}
4.2 使用C++标准库实现优先级队列
C++ STL 提供了内置的优先级队列std::priority_queue,使用起来非常方便。
#include <iostream>
#include <queue>
#include <vector>int main() {// 默认是最大堆std::priority_queue<int> pq;// 插入元素pq.push(10);pq.push(20);pq.push(5);// 查看和删除堆顶元素std::cout << "Top element: " << pq.top() << std::endl; // 输出 20pq.pop();std::cout << "Top element after pop: " << pq.top() << std::endl; // 输出 10// 最小堆的实现std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap;minHeap.push(10);minHeap.push(20);minHeap.push(5);std::cout << "Top element of minHeap: " << minHeap.top() << std::endl; // 输出 5return 0;
}
5. 优先级队列的应用场景
优先级队列在许多场景中有着广泛的应用:
- 任务调度:操作系统为任务分配资源时,根据任务的优先级进行处理。
- 最短路径算法:如Dijkstra和A*算法,利用优先级队列动态选择路径。
- 数据流处理:实时系统中,优先级队列保证关键数据优先处理。
6. 总结
通过本文的介绍,我们从理论到代码,详细解析了优先级队列的实现与应用。手动实现的优先级队列让我们理解了堆的原理,而C++ STL的std::priority_queue提供了高度优化的工具,便于快速开发。掌握优先级队列不仅能提高算法效率,也能帮助我们更灵活地解决实际问题。
7. 延伸阅读
- C++ STL 中的堆算法:
std::make_heap、std::push_heap、std::pop_heap - 二叉堆与平衡树的比较
- 优先级队列的内存优化技术
通过这篇博客,读者将能够深入理解优先级队列的设计思路和实现方法,并学会在实际开发中灵活运用C++的标准工具,提升程序效率和代码质量。
路虽远,行则将至;事虽难,做则必成
下篇文章再会!!!
相关文章:
【C++篇】排队的艺术:用生活场景讲解优先级队列的实现
文章目录 须知 💬 欢迎讨论:如果你在学习过程中有任何问题或想法,欢迎在评论区留言,我们一起交流学习。你的支持是我继续创作的动力! 👍 点赞、收藏与分享:觉得这篇文章对你有帮助吗࿱…...
VTK的基本概念(一)
文章目录 三维场景的基本要素1.灯光2.相机3.颜色4.纹理映射 三维场景的基本要素 1.灯光 在三维渲染场景中,可以有多个灯光的存在,灯光和相机是三维渲染场景的必备要素,如果没有指定的话,vtkRenderer会自动创建默认的灯光和相机。…...
error LNK2001: 无法解析的外部符号 memcpy strcmp strlen
0>LIBMY_static.lib(pixdesc.obj) : error LNK2001: 无法解析的外部符号 __imp_abort 10>LIBMY_static.lib(random_seed.obj) : error LNK2001: 无法解析的外部符号 __imp_abort 10>postprocess.obj : error LNK2001: 无法解析的外部符号 __imp_abort 10>LIBMY_sta…...
打造智能扩容新纪元:Kubernetes Custom Metrics深度解析
自定义指标:Kubernetes Auto Scaling的革命 1. 引言 1.1 Kubernetes与Auto Scaling Kubernetes作为当今容器编排的事实标准,提供了强大的自动化能力,其中Auto Scaling(自动扩缩容)是其核心特性之一。Auto Scaling允许Kubernetes集群根据当前负载动态调整资源,以应对不…...
【K8s】专题十五(4):Kubernetes 网络之 Calico 插件安装、切换网络模式、卸载
本文内容均来自个人笔记并重新梳理,如有错误欢迎指正! 如果对您有帮助,烦请点赞、关注、转发、订阅专栏! 专栏订阅入口 | 精选文章 | Kubernetes | Docker | Linux | 羊毛资源 | 工具推荐 | 往期精彩文章 【Docker】(全…...
Unity类银河战士恶魔城学习总结(P141 Finalising ToolTip优化UI显示)
【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili 教程源地址:https://www.udemy.com/course/2d-rpg-alexdev/ UI部分暂时完结!!! 本章节优化了UI中物品描述的显示效果,技能描述的显示效果 并且可以批…...
c++(入门)
1. 引用 引用的定义 引用是另一个变量的别名,它在声明时必须被初始化,并且一旦初始化后,它就始终引用那个变量。 引用的语法 引用的声明方式是在变量名前加上&符号。 引用的特点 引用必须在声明时初始化。引用一旦初始化后&#x…...
【优选算法】前缀和
目录 一、[【模板】前缀和](https://www.nowcoder.com/practice/acead2f4c28c401889915da98ecdc6bf?tpId230&tqId2021480&ru/exam/oj&qru/ta/dynamic-programming/question-ranking&sourceUrl%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595…...
Spring Bean 的生命周期详解
所谓万物皆对象,对于一个 bean 而言,从出生到死亡,他要经历哪些阶段呢? 生命周期 理解对象的生命周期,可以帮助我们更好的做一些扩展。 一个对象从被创建到被垃圾回收,可以大致分为这 5 个阶段:…...
MySQL【知识改变命运】12
视图 1:什么是视图2:创建视图使用视图(视图的好处)2.1.隐藏敏感字段2.2.对外提供统一访问3:视图和真实表进⾏表连接查询 4:修改视图数据4.1:通过真实表修改数据,会影响视图4.2&#…...
shell编程(完整版)
目录 一、shell脚本解释器 二、shell脚本的执行 三、变量的使用 四、永久环境变量 按用户设置永久环境变量 文件路径: 示例步骤: 删除永久环境变量 五、脚本程序传递参数怎么实现 六、用编程进行数学运算 shell中利用expr进行运算 运算与变量…...
数字逻辑(一)——导论
1.导论 1.1什么是数字逻辑? 数字逻辑是指在数字电路设计、计算机科学领域中对于离散的二进制信号进行逻辑处理、运算、存储和传输的基本原理和方法。 1.2数字量和模拟量的区别 数字量:在时间上和数量上都是离散的、不连续的物理量。模拟量࿱…...
量化交易系统开发-实时行情自动化交易-4.4.做市策略
19年创业做过一年的量化交易但没有成功,作为交易系统的开发人员积累了一些经验,最近想重新研究交易系统,一边整理一边写出来一些思考供大家参考,也希望跟做量化的朋友有更多的交流和合作。 接下来继续说说做市策略原理。 做市策…...
《线性代数的本质》
之前收藏的一门课,刚好期末复习,顺便看一看哈哈 课程链接:【线性代数的本质】合集-转载于3Blue1Brown官方双语】 向量究竟是什么 线性代数中最基础、最根源的组成部分就是向量,需要先明白什么是向量 不同专业对向量的看法 物理专…...
Gbase8s 允许内置用户创建用户以及创建只读权限用户以及利用角色管理普通用户权限
Gbase8s 允许内置用户创建用户以及创建只读权限用户以及利用角色管理普通用户权限 普通安装实例创建数据库以后,DBA权限只有gbasedbt用户。gbasdbt可以创建普通用户,并且给普通用户赋予库及权限或者表级权限。 但是gbasedbt用户口令和操作系统相关,所以想在不提供gbasedbt的…...
24/11/25 视觉笔记 深度传感器和手势识别
本章的目的是开发一个应用程序,使用深度传感器的输出实时检测和跟踪简单的手势。该应用程序将分析每个已捕捉的帧。并执行以下任务。 手部区域分割:通过分析Kinect传感器的深度图输出,在每一帧中提取用户的手部区域,这是通过阈值…...
迄今为止的排序算法总结
迄今为止的排序算法总结 7.10 迄今为止的排序算法总结复杂度和稳定性时间复杂度测试程序sortAlgorithm.hsortAlgorithm.cpptest.cpp 时间复杂度测试结果 7.10 迄今为止的排序算法总结 复杂度和稳定性 排序算法平均情况最好情况最坏情况稳定性空间复杂度选择排序O(n^2)O(n^2)O…...
HTML和CSS 表单、表格练习
HTML和CSS 表格练习 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>HTML表格练习</title>…...
H5流媒体播放器EasyPlayer.js网页直播/点播播放器如果H.265视频在播放器上播放不流畅,可以考虑的解决方案
随着流媒体技术的迅速发展,H5流媒体播放器已成为现代网络视频播放的重要工具。其中,EasyPlayer.js网页直播/点播播放器作为一款功能强大的H5播放器,凭借其全面的协议支持、多种解码方式以及跨平台兼容性,赢得了广泛的关注和应用。…...
Http 转 https 中 Nginx 的详细配置过程
摘要 本节将简要介绍从 HTTP 到 HTTPS 的配置过程,并完整展示 Nginx 的相关配置信息。 经过两天断断续续的调试,终于将 http 变成 https 了。现在说说这个安装 ssl 证书的过程。 服务器是在某云上。这个过程大致分为三个步骤:申请 ssl 证书、…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
