优先队列 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 详解


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

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

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

相关文章

Matplotlib

一、Matplotlib快速入门 学习目标 了解什么是matplotlib 为什么要学习matplotlib matplotlib简单图形的绘制 1、什么是Matplotlib 是专门用于开发2D图表(包括3D图表) 以渐进、交互式方式实现数据可视化 2、为什么要学习Matplotlib 可视化是在整个数据挖掘的关键辅助工…

【leetcode hot 100 131】分割回文串

解法一&#xff1a;回溯法动态规划法 回溯法&#xff1a; 假设我们当前搜索到字符串的第 i 个字符&#xff0c;且 s[0…i−1] 位置的所有字符已经被分割成若干个回文串&#xff0c;并且分割结果被放入了答案数组 ans 中&#xff0c;那么我们就需要枚举下一个回文串的右边界 j…

ToDesk云电脑各类鼠标有什么区别?虚拟/3D/游戏鼠标等各有利

不知道各位在使用ToDesk云电脑的时候是否是有注意到&#xff0c;这其中的鼠标竟有多种名称、多种模式可以选&#xff0c;比如锁定鼠标、3D鼠标、游戏鼠标这几项。 那么这些不同名称的鼠标都代表什么意思呐&#xff0c;又应该怎么选择、怎么用呐&#xff1f;本篇内容小编就为大…

手机怎么换网络IP有什么用?操作指南与场景应用‌

在数字化时代&#xff0c;手机已经成为我们日常生活中不可或缺的一部分&#xff0c;无论是工作、学习还是娱乐&#xff0c;手机都扮演着至关重要的角色。而在手机的使用过程中&#xff0c;网络IP地址作为设备在互联网上的唯一标识符&#xff0c;其重要性和作用不容忽视。本文将…

Bulk Rename Utility(BRU)——大批量重命名实用程序

Bulk Rename Utility&#xff08;BRU&#xff09;——大批量重命名实用程序 博主要给博客网站搞博客封面&#xff0c;几百张图没编号&#xff0c;一弄这个就好了&#xff0c;亲测十分好用&#xff0c;下面的b站教程更是一绝&#xff0c;快快使用起来 文章目录 Bulk Rename Ut…

鸿蒙生态开发

鸿蒙生态开发概述 鸿蒙生态是华为基于开源鸿蒙&#xff08;OpenHarmony&#xff09;构建的分布式操作系统生态&#xff0c;旨在通过开放共享的模式连接智能终端设备、操作系统和应用服务&#xff0c;覆盖消费电子、工业物联网、智能家居等多个领域。以下从定义与架构、核心技术…

Matlab概率区间预测全家桶更新了,新增光伏出力区间预测,4种分布可供预测

基本介绍 适用于matlab2020及以上。可任意选择置信区间&#xff0c;区间覆盖率picp、区间平均宽度百分比等等&#xff0c;可用于预测不确定性&#xff0c;效果如图所示&#xff0c;采用KDE&#xff0c;4种分布进行预测&#xff0c;有对比&#xff0c;可以替换成自己的数据。 …

C语言【文件操作】详解中(会使用fgetc,fputc,fgets,fputs,fscanf,fprintf,fread,fwrite函数)

引言 介绍和文件操作中文件的顺序读写相关的函数 看这篇博文前&#xff0c;希望您先仔细看一下这篇博文&#xff0c;理解一下文件指针和流的概念&#xff1a;C语言【文件操作】详解上-CSDN博客文章浏览阅读606次&#xff0c;点赞26次&#xff0c;收藏4次。先整体认识一下文件是…

深入剖析Java虚拟机(JVM):从零开始掌握Java核心引擎

&#x1f4cc; 引言&#xff1a;为什么每个Java开发者都要懂JVM&#xff1f; 想象你是一名赛车手&#xff0c;Java是你的赛车&#xff0c;而JVM就是赛车的引擎。 虽然你可以不关心引擎内部构造就能开车&#xff0c;但要想在比赛中获胜&#xff0c;必须了解引擎如何工作&#…

鸿蒙harmonyOS笔记:练习CheckBoxGroup获取选中的值

除了视觉效果实现全选和反选以外&#xff0c;咱们经常需要获取选中的值&#xff0c;接下来看看如何实现。 核心步骤&#xff1a; 1. 给 CheckBoxGroup 注册 onChange。 2. CheckBox 添加 name 属性。 3. 在 onChange 的回调函数中获取 选中的 name 属性。 事件&#xff1a…

通俗易懂搞懂@RequestParam 和 @RequestBody

&#x1f4cc; 博主简介: &#x1f4bb; 努力学习的 23 级科班生一枚 &#x1f680;&#x1f3e0; 博主主页 &#xff1a; &#x1f4ce; 灰阳阳&#x1f4da; 往期回顾 &#xff1a;Session和Cookie我不允许你不懂&#x1f4ac; 每日一言&#xff1a; 「流水不争先&#xff0c…

Flink 内存管理

一、内存模型 上图是一个 Flink 程序进程总体的内存模型,其包含 Flink 使用内存、JVM 元空间以及 JVM 开销。 Flink 使用了堆上内存和堆外内存;框架内存使用了堆上内存和堆外内存的直接内存;Task 使用堆上内存和堆外内存的直接内存;管理内存、JVM 元空间以及 JVM 内存开销使…

【工具变量】中国各地级市是否属于“信息惠民国家试点城市”匹配数据(2010-2024年)

数据来源&#xff1a;国家等12部门联合发布的《关于加快实施信息惠民工程有关工作的通知》 数据说明&#xff1a;内含原始文件和匹配结果&#xff0c;当试点城市在2014年及以后&#xff0c;赋值为1&#xff1b;试点城市在2014年之前或该城市从未实施信息惠民试点工程&#x…

git的底层原理

git的底层原理 三段话总结git&#xff0c; 1. 工作原理&#xff1a;git管理是一个DAG有向无环图&#xff0c;HEAD指针指向branch或直接指向commit&#xff0c;branch指向commit&#xff0c;commit指向tree&#xff0c;tree指向别的tree或直接指向blob。 2. git所管理的一个目录…

安装React开发者工具

我们在说组件之前&#xff0c;需要先安装一下React官方推出的开发者工具&#xff0c;首先我们分享在线安装方式 首先打开谷歌网上应用商店(针对谷歌浏览器)&#xff0c;在输入框内搜索react&#xff0c;安装如下插件&#xff1a; 注意安装提供方为Facebook的插件&#xff0c;这…

排列与二进制

#include<iostream> using namespace std; int count_two(int n,int m){int count0;for(int i0;i<m;i){ //统计2的因子个数 int numn-i;while(num%20){count;num /2;}}return count; } int main(){int n,m;while(1){cin >> n >> m;if(n0 && m0)br…

鱼书--学习2

6. 与学习相关的技巧 6.1 参数的更新 &#xff08;1&#xff09; SGD的缺点&#xff1a;SGD低效的根本原因是&#xff0c;梯度的方向并没有指向最小值的方向 基于SGD的最优化的更新路径&#xff1a;呈“之”字形朝最小值(0, 0)移动&#xff0c;效率低 &#xff08;2&#x…

基于SSM框架的汽车租赁平台(源码+lw+部署文档+讲解),源码可白嫖!

摘要 时代在飞速进步&#xff0c;每个行业都在努力发展现在先进技术&#xff0c;通过这些先进的技术来提高自己的水平和优势&#xff0c;汽车租赁平台当然不能排除在外。汽车租赁平台是在实际应用和软件工程的开发原理之上&#xff0c;运用Java语言以及SSM框架进行开发&#x…

LangChain Chat Model学习笔记

Prompt templates: Few shot、Example selector 一、Few shot(少量示例) 创建少量示例的格式化程序 创建一个简单的提示模板&#xff0c;用于在生成时向模型提供示例输入和输出。向LLM提供少量这样的示例被称为少量示例&#xff0c;这是一种简单但强大的指导生成的方式&…

新配置了一台服务器+域名共178:整个安装步骤,恢复服务

买了一台服务器域名eesou.com&#xff1a; 服务器选的是99元最低配的&#xff0c;用免费的镜像&#xff1a;宝塔面板 eesou.com是一口价买的 79&#xff0c;原来wjsou.com卖了。 原来的配置全丢了。开始重新安装步骤。 域名备案才能用&#xff0c;提交就等着了 服务器配置 …