当前位置: 首页 > article >正文

优先队列 priority_queue详解

 说到,priority_queue优先队列。必须先要了解啥是与运算符重载(我在下方有解释)。

否则只知皮毛,极易忘记==寸步难行。

但在开头,还是简单的说下怎么用

首先,你需要调用

#include <queue>

在main函数中,声明格式为:priority_queue<结构类型> 队列名;

priority_queue <int> i;
priority_queue <double> d;

常用操作

priority_queue<int> p;
p.size(); // 获取长度
p.empty(); // 是否为空
p.push(val); // 插入
p.pop(); // 删除首个元素
p.top(); // 获取头部元素

以下是完整应用:

priority_queue隶属于<queue>

而queue又是容器适配器。

故,priority_queue也是容器适配器

容器适配器 代表这个函数底层,是可插拔的,能用(vector、deque实现)。
但要注意list不能作为底层容器,因为list不支持随机访问 (如operator[])
简而言之,priority_queue就像汽车,而内部的发动机,有原装的。如果你不满意,也可以换成其他!

priority_queue<int,vector<int>,cmp> pq;vector<int>就是其底层默认的容器,cmp是重载过后的(结构体or类)
初识:
#include <iostream>
#include <queue>
using namespace std;
struct cmp{bool operator()(int a,int b){return a<b; // 因为是正常比较,固为最大堆// return a>b 最小堆}
};
int main(){priority_queue<int,vector<int>,cmp> pq; pq.push(3);pq.push(2);pq.push(1);while(pq.size()!=0){cout<<pq.top()<<endl;pq.pop();}return 0;
}

我看了很多博客,大多数博主,重载的符号都是<符号,而不是(),咱们就在这里说一说。

重载 operator< 的优点

  • 简单直观:直接在类中定义比较逻辑,适合类本身需要一个固定的排序规则。

  • 通用性:不仅适用于 priority_queue,还适用于其他需要比较的场景,如 sort 函数。

自定义比较函数对象的优点

  • 灵活性:可以在不修改类定义的情况下,为不同的排序需求提供多种比较逻辑。

  • 避免全局污染:比较逻辑封装在函数对象中,不会影响类的全局比较行为。

源码中的关键逻辑

priority_queue的底层实现中,堆调整(如pushpop)时会调用比较器:

// 伪代码:堆的上浮操作
void _upheap(int i) {while (i > 0) {int parent = (i-1)/2;if (Compare()(heap[parent], heap[i])) { // 调用operator()swap(heap[parent], heap[i]);i = parent;} else break;}
}
底层的简单实现:

其实一下代码,就是的低配版,只要知道什么是堆排序,就能够轻松解决优先队列。

#include <iostream>
#include <vector>template <typename T>
class PriorityQueue {
private:std::vector<T> heap;// 上浮操作,用于维护堆的性质void siftUp(int index) {while (index > 0) {int parent = (index - 1) / 2;if (heap[parent] >= heap[index]) {break;}std::swap(heap[parent], heap[index]);index = parent;}}// 下沉操作,用于维护堆的性质void siftDown(int index) {int size = heap.size();while (true) {int leftChild = 2 * index + 1;int rightChild = 2 * index + 2;int largest = index;if (leftChild < size && heap[leftChild] > heap[largest]) {largest = leftChild;}if (rightChild < size && heap[rightChild] > heap[largest]) {largest = rightChild;}if (largest == index) {break;}std::swap(heap[index], heap[largest]);index = largest;}}public:// 判断队列是否为空bool empty() const {return heap.empty();}// 获取队列的大小size_t size() const {return heap.size();}// 获取堆顶元素T top() const {if (empty()) {throw std::out_of_range("Priority queue is empty");}return heap[0];}// 插入元素void push(const T& value) {heap.push_back(value);siftUp(heap.size() - 1);}// 删除堆顶元素void pop() {if (empty()) {throw std::out_of_range("Priority queue is empty");}std::swap(heap[0], heap.back());heap.pop_back();siftDown(0);}
};int main() {PriorityQueue<int> pq;pq.push(3);pq.push(1);pq.push(2);std::cout << "Top element: " << pq.top() << std::endl;pq.pop();std::cout << "Top element after pop: " << pq.top() << std::endl;return 0;
}    
大纲

一、前 K 个高频元素-(解析)-结合unordered_map复合运用,了解map的最小单位pair

二、滑动窗口最大值-(解析)-pair<int,int>复合运用,滑动窗口实践

三、 游戏 蓝桥真题-(解析)-相当于上两道题结合运用

( •̀ ω •́ )✧点击这里,继续学习其他模块吧!

题目:
一、前 K 个高频元素

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

示例 1:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

示例 2:

输入: nums = [1], k = 1
输出: [1]

提示:

  • 1 <= nums.length <= 105
  • k 的取值范围是 [1, 数组中不相同的元素的个数]
  • 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的
class Solution {struct cmp{bool operator()(pair<int,int> p1, pair<int,int> p2){return p1.second<p2.second; // 正常比较}};
public:vector<int> topKFrequent(vector<int>& nums, int k) {unordered_map<int,int> umap;for(int i : nums){umap[i]++;}priority_queue<pair<int,int>,vector<pair<int,int>>,cmp>pq;for(auto it = umap.begin(); it!=umap.end(); ++it){pq.push(*it);}vector<int> vec;while(k--){vec.push_back(pq.top().first);pq.pop();}return vec;}
};
二、滑动窗口最大值

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 

示例 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       31 [3  -1  -3] 5  3  6  7       31  3 [-1  -3  5] 3  6  7       51  3  -1 [-3  5  3] 6  7       51  3  -1  -3 [5  3  6] 7       61  3  -1  -3  5 [3  6  7]      7

示例 2:

输入:nums = [1], k = 1
输出:[1]

提示:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104
  • 1 <= k <= nums.length
class Solution {struct cmp{bool operator()(const pair<int,int>& p1,const pair<int,int>& p2){return p1.first<p2.first;}};
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {vector<int> vec;priority_queue<pair<int,int>,vector<pair<int,int>>,cmp> p;for(int i=0; i<k; ++i){p.push({nums[i],i});}// 添加第一个滑动窗口的最大值vec.push_back(p.top().first);for(int i=k; i<nums.size(); ++i){p.push({nums[i],i});while(p.top().second<=i-k) p.pop();vec.push_back(p.top().first);}return vec;}
};
三、 游戏 蓝桥真题

问题描述

熊大和熊二在玩游戏。他们将 nn 个正整数 a1,a2,...,ana1​,a2​,...,an​ 排成一行,然后各用一个长度为 kk 的框在这个数组中各自随机框选出一段长度为 kk 的连续子序列(随机框选指在合法的 n−k+1nk+1 个连续子序列中均匀随机)。熊大记录了他框出的 kk 个数中的最大值 PP,熊二记录了他框出的 kk 个数的最小值 QQ,他们突然有个疑问:P−QPQ 的期望是多少?

2024-11-27 Update:Java 时限调整至 1s

输入描述

输入共 22 行。

第一行为两个正整数 n,kn,k

第二行为 nn 个由空格隔开的正整数 a1,a2,...,ana1​,a2​,...,an​。

输出描述

输出共 11 行,一个浮点数(请保留两位小数)。

样例输入

3 2
1 2 3 

样例输出

1.00

样例说明

一共有四种情况:

熊大框出 [1,2][1,2],P=2P=2;熊二框出 [1,2][1,2],Q=1Q=1,P−Q=1PQ=1。

熊大框出 [1,2][1,2],P=2P=2;熊二框出 [2,3][2,3],Q=2Q=2,P−Q=0PQ=0。

熊大框出 [2,3][2,3],P=3P=3;熊二框出 [1,2][1,2],Q=1Q=1,P−Q=2PQ=2。

熊大框出 [2,3][2,3],P=3P=3;熊二框出 [2,3][2,3],Q=2Q=2,P−Q=1PQ=1。

所以 P−QPQ 的期望为(1+0+2+1)/4=1.00(1+0+2+1)/4=1.00。

评测用例规模

对于 20%20% 的数据,保证 n≤102n≤102。

对于 40%40% 的数据,保证 n≤103n≤103。

对于 100%100% 的数据,保证 n≤105n≤105,0<ai≤1090<ai​≤109,0<k≤n0<kn

#include <iostream>
#include <queue>
#define ll long long
using namespace std;
struct max_cmp{bool operator()(const pair<ll,int>& p1,const pair<ll,int>& p2){ // 最大堆return p1.first<p2.first;}
};
struct min_cmp{bool operator()(const pair<ll,int>& p1,const pair<ll,int>& p2){ // 最小堆return p1.first>p2.first;}
};
int main()
{priority_queue<pair<ll,int>,vector<pair<ll,int>>,max_cmp> max_p;priority_queue<pair<ll,int>,vector<pair<ll,int>>,min_cmp> min_p;int n,k;cin>>n>>k;for(int i=0; i<k; ++i){ // 拓展ll cur;cin>>cur;max_p.push({cur,i});min_p.push({cur,i});}int P,Q;P = max_p.top().first;Q = min_p.top().first;ll sum = P-Q;for(int i=k; i<n; ++i){ // 增加while(!max_p.empty()&&max_p.top().second<=i-k) max_p.pop();while(!min_p.empty()&&min_p.top().second<=i-k) min_p.pop();ll cur;cin>>cur;max_p.push({cur,i});min_p.push({cur,i});P = max_p.top().first;Q = min_p.top().first;sum += P-Q;}printf("%.2lf",(double)sum/(n-k+1));return 0;
}

知识点:
重载函数与重载运算符 :: 基础巩固 ::

这里我着重要掌握的是,重载运算符

重载函数

在同一作用域中,可以声明几个功能类似的同名函数。但是形式参数(指参数类型、顺序等)必须不同。如下:

#include <iostream>
using namespace std;\
struct printData{
public:void print(int i){cout<<i<<endl;}void print(double i){cout<<i<<endl;}void print(char c[]){cout<<c<<endl; }
};
int main(){printData pd;pd.print(3);return 0;
}

重载运算符

语法格式:

class 类名
{
public:返回类型 operator 运算符 (参数列表){// 运算符的具体运算过程}
}

普通成员函数,以标识符作为函数名。
而重载函数,以 "operator 函数名" 作为函数名。其中operator 表示这是一个重载的运算符。
而后的运算符,就是我们要定义的符号。

如:

a+b;
实际等同于
a.operator + (b)

实例操作:

class Box
{private:double length;      // 长度double breadth;     // 宽度double height;      // 高度// 重载 + 运算符,用于把两个 Box 对象相加Box operator+(const Box& b){Box box;box.length = this->length + b.length;box.breadth = this->breadth + b.breadth;box.height = this->height + b.height;return box;}};Box3 = Box1 + Box2;

为啥用 this 时,有->:
在 C++ 中,每一个非静态成员函数都有一个隐含的指针形参,即this指针。
this指针指向调用该成员函数的对象,它是一个常量指针,其类型为类名* const 。

期望 :: 数学知识 ::

期望的由来赌硬币

基础忘记时,可以看看堵硬币


借鉴博客:

1、C++ 重载运算符和重载函数

2、C++中的运算符重载(非常详细)

3、【原创】优先队列 priority_queue 详解


( •̀ ω •́ )✧点击这里,继续学习其他模块吧! 

相关文章:

优先队列 priority_queue详解

说到&#xff0c;priority_queue优先队列。必须先要了解啥是堆与运算符重载(我在下方有解释)。 否则只知皮毛&#xff0c;极易忘记寸步难行。 但在开头&#xff0c;还是简单的说下怎么用 首先&#xff0c;你需要调用 #include <queue> 在main函数中&#xff0c;声明…...

《信息系统安全》(第一次上机实验报告)

实验一 &#xff1a;网络协议分析工具Wireshark 一 实验目的 学习使用网络协议分析工具Wireshark的方法&#xff0c;并用它来分析一些协议。 二实验原理 TCP/IP协议族中网络层、传输层、应用层相关重要协议原理。网络协议分析工具Wireshark的工作原理和基本使用规则。 三 实…...

C++实现求解24点游戏

力扣原题&#xff1a;679. 24 点游戏 - 力扣&#xff08;LeetCode&#xff09; 判断四个数字能否通过加减乘除得到24点 使用回溯遍历四个数字的每一种组合&#xff0c;具体来说&#xff0c;每次从数组中选取两个数字以加减乘除四种方式得到一个新的数字&#xff0c;这样数组的…...

Java-腾讯云短信模板兼容阿里云短信模板-短信模板参数生成

最新版本更新 https://code.jiangjiesheng.cn/article/362?fromcsdn 模板 腾讯云&#xff1a;您好&#xff01;{}的${}&#xff0c;有{}发生{} 阿里云&#xff1a;您好&#xff01;${orgName}的${monitorName}&#xff0c;有${equipName}发生${status} 原腾讯云短信发送的代码…...

简要分析IPPROTO_TCP参数

IPPROTO_TCP是操作系统或网络编程中定义的一个 协议号常量&#xff0c;用于标识 传输控制协议&#xff08;TCP&#xff09;。其核心作用是 在传输层指定使用TCP协议&#xff0c;确保数据通过TCP的可靠传输机制进行通信。 一、定义与值 头文件&#xff1a;定义在<netinet/in.…...

SOFABoot-06-健康检查

前言 大家好&#xff0c;我是老马。 sofastack 其实出来很久了&#xff0c;第一次应该是在 2022 年左右开始关注&#xff0c;但是一直没有深入研究。 最近想学习一下 SOFA 对于生态的设计和思考。 sofaboot 系列 SOFABoot-00-sofaboot 概览 SOFABoot-01-蚂蚁金服开源的 s…...

如何理解java中Stream流?

在Java中&#xff0c;Stream 是 Java 8 引入的一个强大API&#xff0c;用于处理集合&#xff08;如 List、Set、Map 等&#xff09;数据的流式操作。它提供了一种声明式、函数式的编程风格&#xff0c;可以高效地进行过滤、映射、排序、聚合等操作。 Stream 的核心概念 流&…...

Android使用RxHttp进行国密4加密解密

国密SM4加解密问题汇总 前言国密4加解密工具类RxHttp统一加解密处理解密前言 为了网络安全需要对app内请求数据接口使用SM4国密4进行加解密操作,在实施的过程中遇到了些问题 也收获颇丰,特此记录 在线SM4加密测试网址: 点击此进入网址. 国密4加解密工具类 这里我使用的是b…...

【自学笔记】Linux基础知识点总览-持续更新

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Linux 基础知识点总览目录Linux 简介文件和目录结构常用命令文件操作目录操作权限管理文本处理 Shell 脚本基础进程管理用户和组管理网络配置 总结 Linux 基础知识点…...

JavaScript与客户端开发

1、简介 简单的讲&#xff0c;JavaScript是一种脚本语言&#xff0c;为网站提供了一种在客户端运行程序的手段&#xff0c;通过它可以实现客户端数据验证、网页特效等功能。 JavaScript是一种基于对象和事件驱动&#xff08;不懂啥意思&#xff0c;暂不管它&#xff09;&…...

基于CNN的FashionMNIST数据集识别5——GoogleNet模型

源码 import torch from torch import nn from torchsummary import summaryclass Inception(nn.Module):def __init__(self, in_channels, c1, c2, c3, c4):super().__init__()self.ReLu nn.ReLU()#路径1self.p1_1 nn.Conv2d(in_channelsin_channels, out_channelsc1, kern…...

JVM垃圾回收笔记01-垃圾回收算法

文章目录 前言1. 如何判断对象可以回收1.1 引用计数法1.2 可达性分析算法查看根对象哪些对象可以作为 GC Root ?对象可以被回收&#xff0c;就代表一定会被回收吗&#xff1f; 1.3 引用类型1.强引用&#xff08;StrongReference&#xff09;2.软引用&#xff08;SoftReference…...

【初探数据结构】树与二叉树

&#x1f4ac; 欢迎讨论&#xff1a;在阅读过程中有任何疑问&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;如果你觉得这篇文章对你有帮助&#xff0c;记得点赞、收藏&#xff0c;并分享给更多对数据结构感…...

numpy学习笔记10:arr *= 2向量化操作性能优化

numpy学习笔记10&#xff1a;arr * 2向量化操作性能优化 在 NumPy 中&#xff0c;直接对整个数组进行向量化操作&#xff08;如 arr * 2&#xff09;的效率远高于显式循环&#xff08;如 for i in range(len(arr)): arr[i] * 2&#xff09;。以下是详细的解释&#xff1a; 1. …...

蓝桥杯备考:二分答案之路标设置

最大距离&#xff0c;找最小空旷指数值&#xff0c;我们是很容易想到用二分的&#xff0c;我们再看看这个答案有没有二段性 是有这么个二段性的&#xff0c;我们只要二分就行了&#xff0c;但是二分的check函数是有点不好想的&#xff0c;我们枚举空旷值的时候&#xff0c;为了…...

回调方法传参汇总

文章目录 0. 引入问题1. 父子组件传值1.1 父传子&#xff1a;props1.2 子传父&#xff1a;$emit1.3 双向绑定&#xff1a;v-model 2. 多个参数传递3. 父组件监听方法传递其他值3.1 $event3.2 箭头方法 4. 子组件传递多个参数&#xff0c;父组件传递本地参数4.1 箭头函数 … 扩…...

在 Linux下使用 Python 3.11 和 FastAPI 搭建带免费证书的 HTTPS 服务器

在当今数字化时代&#xff0c;保障网站数据传输的安全性至关重要。HTTPS 协议通过使用 SSL/TLS 加密技术&#xff0c;能够有效防止数据在传输过程中被窃取或篡改。本教程将详细介绍如何在 Ubuntu 22.04 系统上&#xff0c;使用 Python 3.11 和 FastAPI 框架搭建一个带有免费 SS…...

XSS基础靶场练习

目录 1. 准备靶场 2. PASS 1. Level 1&#xff1a;无过滤 源码&#xff1a; 2. level2&#xff1a;转HTML实体 htmlspecialchars简介&#xff1a; 源码 PASS 3. level3:转HTML深入 源码&#xff1a; PASS 4. level4:过滤<> 源码&#xff1a; PASS: 5. level5:过滤on 源码…...

Redis核心机制(一)

目录 Redis的特性 1.速度快 2.以键值对方式进行存储 3.丰富的功能 4.客户端语言多 5.持久化 6.主从复制 7.高可用和分布式 Redis使用场景 Redis核心机制——持久化 RDB bgsave执行流程 ​编辑 AOF AOF重写流程 3.混合持久化&#xff08;RDBAOF&#xff09; Red…...

QGroupBox取消勾选时不禁用子控件

默认情况下&#xff0c;QGroupBox取消勾选会自动禁用子控件&#xff0c;如下图所示 那么如何实现取消勾选时不禁用子控件呢&#xff1f; 实现很简单&#xff0c;直接上代码了 connect(ui->groupBox, &QGroupBox::toggled, this, [](bool checked){if (checked false){…...

Go语言中package的使用规则《二》

在 Go 语言中&#xff0c;包&#xff08;Package&#xff09; 是代码组织和复用的核心单元。以下是其定义、引用规则及使用习惯的详细说明&#xff1a; 一、包的定义规则 目录与包名 一个包对应一个目录&#xff08;文件夹&#xff09;&#xff0c;目录名通常与包名一致。 包名…...

MyBatis-Plus 自动填充:优雅实现创建/更新时间自动更新!

目录 一、什么是 MyBatis-Plus 自动填充&#xff1f; &#x1f914;二、自动填充的原理 ⚙️三、实际例子&#xff1a;创建时间和更新时间字段自动填充 ⏰四、注意事项 ⚠️五、总结 &#x1f389; &#x1f31f;我的其他文章也讲解的比较有趣&#x1f601;&#xff0c;如果喜欢…...

canvas数据标注功能简单实现:矩形、圆形

背景说明 基于UI同学的设计&#xff0c;在市面上找不到刚刚好的数据标注工具&#xff0c;遂决定自行开发。目前需求是实现图片的矩形、圆形标注&#xff0c;并获取标注的坐标信息&#xff0c;使用canvas可以比较方便的实现该功能。 主要功能 选中图形&#xff0c;进行拖动 使…...

Python 魔术方法深度解析:__getattr__ 与 __getattribute__

一、核心概念与差异解析 1. __getattr__ 的定位与特性 触发时机&#xff1a; 当访问对象中 ​**不存在的属性** 时自动触发&#xff0c;是 Python 属性访问链中的最后一道防线。 核心能力&#xff1a; 动态生成缺失属性实现优雅的错误处理构建链式调用接口&#xff08;如 R…...

【机器学习】机器学习工程实战-第2章 项目开始前

上一章&#xff1a;第1章 概述 文章目录 2.1 机器学习项目的优先级排序2.1.1 机器学习的影响2.1.2 机器学习的成本 2.2 估计机器学习项目的复杂度2.2.1 未知因素2.2.2 简化问题2.2.3 非线性进展 2.3 确定机器学习项目的目标2.3.1 模型能做什么2.3.2 成功模型的属性 2.4 构建机…...

【UI设计】一些好用的免费图标素材网站

阿里巴巴矢量图标库https://www.iconfont.cn/国内最大的矢量图标库之一&#xff0c;拥有 800 万 图标资源。特色功能包括团队协作、多端适配、定制化编辑等&#xff0c;适合企业级项目、电商设计、中文产品开发等场景。IconParkhttps://iconpark.oceanengine.com/home字节跳动…...

Visual Studio(VS)的 Release 配置中生成程序数据库(PDB)文件

最近工作中的一个测试工具在测试多台设备上使用过程中闪退&#xff0c;存了dump&#xff0c;但因为是release版本&#xff0c;没有pdb&#xff0c;无法根据dump定位代码哪块出了问题&#xff0c;很苦恼&#xff0c;查了下怎么加pdb生成&#xff0c;记录一下。以下是具体的设置步…...

ubuntu 解挂载时提示 “umount: /home/xx/Applications/yy: target is busy.”

问题如题所示&#xff0c;我挂载一个squanfs文件系统到指定目录&#xff0c;当我使用完后&#xff0c;准备解挂载时&#xff0c;提示umount: /home/xx/Applications/yy: target is busy.&#xff0c;具体的如图所示&#xff0c; 这种提示通常是表明这个路径的内容正在被某些进…...

一条不太简单的TEX学习之路

目录 rule raisebox \includegraphics newenviro 、\vspace \stretch \setlength 解释&#xff1a; 总结&#xff1a; 、\linespread newcommand \par 小四 \small simple 、mutiput画网格 解释&#xff1a; 图案解释&#xff1a; xetex pdelatex etc index 报…...

Matplotlib完全指南:数据可视化从入门到实战

目录 引言 一、环境配置与基础概念 1.1 安装Matplotlib 1.2 导入惯例 1.3 两种绘图模式 二、基础图形绘制 2.1 折线图&#xff08;Line Plot&#xff09; 2.2 柱状图&#xff08;Bar Chart&#xff09; 三、高级图表类型 3.1 散点图&#xff08;Scatter Plot&#xff…...