Priority_queue

一、priority_queue的介绍和使用

1.1 priority_queue的介绍

1.优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。

2.优先队列类似于堆, 在堆中可以随时插入元素, 并且只能检索最大堆元素(优先队列中位于顶部的元素)。

3.优先队列被实现为容器适配器,容器适配器即将特定的容器类封装作为其底层容器,queue提供一组特定的成员函数来访问其元素,元素从特定容器的尾部弹出,这里称为优先队列的顶部。

4.底层容器可以是任何标准容器类模版,也可以是其他特定设计的容器类,容器应该可以通过随机访问和迭代器访问,需要支持一下操作:

  • empty() : 判断容器是否为空

  • size() : 返回容器中的有效元素个数

  • front() : 返回容器中的第一个元素的引用

  • push_back() : 在容器中尾插元素

  • pop_back() : 在容器中尾删元素

5.标准容器类vector和deque满足这些需求,默认情况下如果没有指定底层容器的话就默认使用vector作为优先队列的底层容器。

6.需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器通过在需要时自动调用算法函数make_heap、push_heap、和pop_heap来自动完成此操作。

1.2 priority_queue的使用

优先级队列默认使用vector作为求底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以使用priority_queue来替代。

注意:默认情况下,priority_queue是大堆

函数声明接口说明
priority_queue()/priority_queue(first, last)构造一个空的优先级队列
empty()检测优先级队列是否为空,是的话就返回true否则返回false
top()返回优先级队列中最大(最小)的元素,即堆顶元素(默认是大堆,返回最大元素)
push(x)在优先级队列中插入元素x
pop()删除优先级队列中最大(最小)元素,即删除堆顶元素

下面我们来看下优先队列的使用实例:

#include<iostream>
#include<vector>
#include<queue>
//greater算法的头文件
#include<functional>using namespace std;void test1()
{//默认情况下是建大堆priority_queue<int> q1;vector<int> arr{ 1, 3, 4, 5, 6 , 7, 9, };for (auto& e : arr){q1.push(e);}while (!q1.empty()){cout << q1.top() << " ";q1.pop();}cout << endl;//将第三个模版参数换成great比较方式就是建小堆priority_queue<int, vector<int>, greater<int>> q2(arr.begin(), arr.end());while (!q2.empty()){cout << q2.top() << " ";q2.pop();}cout << endl;}int main()
{test1();return 0;
}

二、OJ练习

leetcode215,数组中的第k个最大元素

题目:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们先看题意是让我们找出数组nums中的第k个最大的元素,看到样例2中我们发现相同的数也会被算进k里面,因此我们在这题上面,就可以利用我们的优先级队列,我们将优先级队列中的前k -1 个元素给pop出去,那么剩下的元素中堆顶元素就是我们的第k个最大元素。

下面是这道题的参考代码:

class Solution {
public:int findKthLargest(vector<int>& nums, int k) {priority_queue<int> q1(nums.begin(), nums.end());//将前k - 1个元素pop掉就是第k个最大元素while(--k) q1.pop();//直接返回优先级队列的堆顶元素即可return q1.top();}
};

三、 priority_queue的模拟实现

3.1 仿函数的概念

仿函数又称为函数对象:重载了operator()的类,类的对象可以向函数一样使用。

operator() 的特点:参数个数和返回值是根据需求定的很灵活。

3.2 仿函数的实现

3.2.1 判断小于的仿函数

下面是我们的判断小于的仿函数的代码:

//判断小于的仿函数
template<class T>
class myless
{
public:bool operator() (T& x, T& y){return x < y;}
};

我们定义了一个重载了operator() 的类,类里面就只有一个重载函数。我们可以通过这种方式来模拟出一个函数。

3.2.2 判断大于的仿函数

下面是我们判断大于的仿函数的代码:

//判断大于的仿函数
template<class T>
class mygreater
{
public:bool operator() (T& x, T& y){return x > y;}
};

这是我们判断大于的仿函数,和判断小于的仿函数的原理相同也是使用了一个类模版,然后再里面重载了一个operator() 函数,用来模拟函数的效果。

3.3 构造以及建堆调整操作

3.3.1 构造函数

这里的构造函数我们先实现默认的无参构造:

//无参构造
priority_queue():c(), comp()
{}

将类里面的两个成员变量给一个空值, c是底层容器,comp是用来比较的仿函数。实现建堆的调整函数后我们在来实现我们的迭代器构造函数。

3.3.2 向上调整建堆

下面是我们进行维持优先级队列的顺序的函数之一,向上调整算法:

//向上调整建堆
void Adjust_up(int child)
{int parent = (child - 1) / 2;while (child > 0){//if (c[parent] < c[child])if(comp(c[parent], c[child])){swap(c[parent], c[child]);}child = parent;parent = (child - 1) / 2;}
}

我们首先要知道用数组模拟堆,也就是优先级队列,它的子节点和父亲节点的下标之间的关系,在向上建堆操作中我们是从下往上的,我们需要知道parent和child之间的关系,它们之间的关系就是 parent = (child - 1) / 2 , 这里的比较我们可以使用仿函数来比较也可以直接实用大于和小于号比较但是建议使用仿函数,因为仿函数的通用性高, 当我们的父节点小于我们的子节点时我们就将他们交换位置,然后将父节点的位置给到子节点,然后重新计算父节点,相当于是更新子节点和父节点。

3.3.3 向下调整建堆

下面是我们的向下调整算法:

//向下调整建堆
void Adjust_down(int parent)
{int child = parent * 2 + 1;if (child + 1 < c.size() && c[child] < c[child + 1]){child++;}while (child < c.size()){//if (c[parent] < c[child])if(comp(c[parent], c[child])){swap(c[parent], c[child]);}parent = child;child = parent * 2 + 1;}
}

向下建堆的效率要比向上调整建堆的效率要高很多, 在我们的迭代器区间构造和我们的pop函数中可以使用我们的向下调整算法来维持优先队列的结构。原理和向上调整建堆基本相同,向下调整算法是传入parent的值,然后计算出child的值,child和parent的关系式是:child = parent * 2 + 1, 然后我们选出最大的左右子节点中较大的那个子节点,对parent和child进行比较,如果parent的值小于child的值的话就将它们调换位置,然后将child的下标给给parent,然后再计算child的下标,相当于更新位置。

3.3.4 使用迭代器区间进行构造

下面是我们的实例代码:

 //迭代器区间构造template <class InputIterator>priority_queue(InputIterator first, InputIterator last):c(),comp(){while (first != last){c.push_back(*first);first++;}for (int i = (c.size() - 1 - 1) / 2; i >= 0; i--){Adjust_down(i);}}

这里我们直接将这个迭代器区间中的值通过迭代器遍历逐个放进我们的底层容器中即可,然后通过我们的向下调整算法进行建堆。

3.4 priority_queue中的容量以及访问访问修改操作

3.4.1 容量相关的接口

我们容量相关的接口有size和empty,size的作用是返回有效数据的个数,empty的作用是判断队列中是否为空。

下面来看我们的size接口:

//返回有效数据个数
size_t size() const
{return c.size();
}

对于我们的size接口就直接返回我们底层容器的size接口的值即可。

再来看下我们的empty接口:

 //判断优先队列里面是否为空bool empty() const{return c.empty();}

与size接口同理empty接口也是直接返回我们的底层容器的接口即可。

3.4.2 访问和修改

关于访问和修改操作的接口有:top, push, pop

下面依次来看这些接口:

top:

 //返回队头元素T& top() {return c[0];}const T& top() const{return c[0];}

top 接口的作用是返回我们的队头元素,我们的底层容器是动态数组vector我们就直接返回数组的第一个元素即可。

push:

//入队操作
//尾插入队,执行向上调整操作
void push(const T& x)
{c.push_back(x);Adjust_up(c.size() - 1);
}

对于入队操作我们直接尾插进数组即可,尾插之后执行向上调整操作。

pop:

//出队操作
//先交换最后一个元素和第一个元素的位置
//尾删出队,执行向下调整操作
void pop()
{swap(c[0], c[size() - 1]);c.pop_back();Adjust_down(0);
}

对于我们pop接口的作用时将堆顶元素给pop出去,我们将堆顶元素和数组最后一个元素进行交换位置,然后进行尾删,最后执行向下调整操作,维持堆的结构即可。


这就是这篇文章的全部内容了,希望大家能从以上内容中对优先级队列有一定的理解。


对于入队操作我们直接尾插进数组即可,尾插之后执行向上调整操作。pop:```C++
//出队操作
//先交换最后一个元素和第一个元素的位置
//尾删出队,执行向下调整操作
void pop()
{swap(c[0], c[size() - 1]);c.pop_back();Adjust_down(0);
}

对于我们pop接口的作用时将堆顶元素给pop出去,我们将堆顶元素和数组最后一个元素进行交换位置,然后进行尾删,最后执行向下调整操作,维持堆的结构即可。


这就是这篇文章的全部内容了,希望大家能从以上内容中对优先级队列有一定的理解。

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

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

相关文章

硕士课程 可穿戴设备之作业一

作业一 第一个代码使用的方法是出自于[1]。 框架结构 如下图&#xff0c;不过根据对代码的解读&#xff0c;发现作者在代码中省去了对SSR部件的实现&#xff0c;下文再说。 Troika框架由三个关键部件组成&#xff1a;信号分解&#xff0c;SSR和光谱峰值跟踪。&#xff08;粗…

word 无法自动检测拼写

word 有时候不能分辨是哪种语言,比如把英语错认为法语 。 例如&#xff1a;Interlaayer spacace,发现误认为是法语。 1、选中Interlaayer spacace 2、点击语言下拉按钮 选择设置校对语言 发现校对语言为法语 3、手动修改校对语言为英语&#xff0c;并点击确认。 4、发现现…

升级鸿蒙4.2新变化,新增 WLAN 网络自动连接开关!

手机已经成为现代人生活中不可或缺的一部分&#xff0c;手机里的功能可以满足大部分人的生活场景&#xff0c;但是最依赖的应该就是手机网络&#xff0c;手机网络突然变差怎么办——消息发不出去&#xff1f;刷新闻速度变慢&#xff1f;仔细检查后&#xff0c;发现其实不是手机…

【一步一步了解Java系列】:重磅多态

看到这句话的时候证明&#xff1a;此刻你我都在努力 加油陌生人 个人主页&#xff1a;Gu Gu Study专栏&#xff1a;一步一步了解Java 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者&#xff1a;小闭…

E10:流程主表表单字段值变化触发事件

效果– //window.WeFormSDK.showMessage("这是一个E10的提示", 3, 2); const onClickCreate () > console.log("create"); const onClickSave () > console.log("save"); const onClickCancel () > dialogComponent?.destroy();/…

Python量化交易学习——Part4:基于基本面的单因子选股策略

技术分析与基本面分析是股票价格分析最基础也是最经典的两个部分。技术分析是针对交易曲线及成交量等指标进行分析,基本面分析是基于公司的基本素质进行分析。 一般来说选股要先选行业,在选个股,之后根据技术分析选择买卖节点,因此针对行业及个股的基本面分析是选股的基础。…

排序算法集合

1. 冒泡排序 排序的过程分为多趟&#xff0c;在每一趟中&#xff0c;从前向后遍历数组的无序部分&#xff0c;通过交换相邻两数位置的方式&#xff0c;将无序元素中最大的元素移动到无序部分的末尾&#xff08;第一趟中&#xff0c;将最大的元素移动到数组倒数第一的位置&…

【scikit-learn010】sklearn算法模型清单实战及经验总结(已更新)

1.一直以来想写下基于scikit-learn训练AI算法的系列文章,作为较火的机器学习框架,也是日常项目开发中常用的一款工具,最近刚好挤时间梳理、总结下这块儿的知识体系。 2.熟悉、梳理、总结下scikit-learn框架模型算法包相关技术点及经验。 3.欢迎批评指正,欢迎互三,跪谢一键…

代码随想录算法训练营day41

题目&#xff1a;01背包理论基础、416. 分割等和子集 参考链接&#xff1a;代码随想录 动态规划&#xff1a;01背包理论基础 思路&#xff1a;01背包是所有背包问题的基础&#xff0c;第一次看到比较懵&#xff0c;完全不知道dp数据怎么设置。具体分析还是dp五部曲&#xff…

C#WPF数字大屏项目实战04--设备运行状态

1、引入Livecharts包 项目中&#xff0c;设备运行状态是用饼状图展示的&#xff0c;因此需要使用livechart控件&#xff0c;该控件提供丰富多彩的图形控件显示效果 窗体使用控件 2、设置饼状图的显示图例 通过<lvc:PieChart.Series>设置环状区域 3、设置饼状图资源样…

js 数字精确度

事情的起源&#xff1a; 项目中 填写的赔付金额是小数 传给后端需要 *100 9.87 *100 传给后端后是986.9999999999999 后端直接取整 就变成了9.86了 0.1 0.2 ! 0.3 console.log(0.1 0.2) //0.30000000000000004 console.log(0.1 0.2 0.3) //false1. 数字的存储 浮点数是用…

【数据库】SQL--DQL(初阶)

文章目录 DCL1. 基本介绍2. 语法2.1 基础查询2.2 条件查询2.3 聚合函数2.4 聚合查询2.5 分组查询2.6 排序查询2.7 分页查询2.8 综合案例练习2.9 执行顺序 3. DQL总结 DCL 更多数据库MySQL系统内容就在以下专栏&#xff1a; 专栏链接&#xff1a;数据库MySQL 1. 基本介绍 DQL英…

全息之镜,未来的眼镜

全息之镜&#xff0c;作为未来眼镜的一种设想和展望&#xff0c;凭借其独特的全息技术&#xff0c;将在未来带来全新的视觉体验和应用场景。以下是关于全息之镜未来的详细分析和展望&#xff1a; 一、技术原理与特点 全息之镜利用全息技术&#xff0c;通过干涉、衍射和折射等…

k8s自定义资源你会创建吗

创建自定义资源定义 CustomResourceDefinition 当你创建新的 CustomResourceDefinition&#xff08;CRD&#xff09;时&#xff0c;Kubernetes API 服务器会为你所 指定的每一个版本生成一个 RESTful 的 资源路径。CRD 可以是名字空间作用域的&#xff0c;也可以是集群作用域的…

4.2 索引及其操作

对数据库中的表进行查询操作时有两种搜索扫描方式&#xff0c;一种是全表扫描&#xff0c;另一种就是使用表上建立的索引进行扫描。 全表扫描要查找某个特定的行&#xff0c;必须从头开始一一查看表中的每一行&#xff0c;与查询条件做对比&#xff0c;返回满足条件的记录&…

JVM学习-Jprofiler

JProfiler 基本概述 特点 使用方便&#xff0c;界面操作友好对被分析的应用影响小(提供模板)CPU&#xff0c;Tread&#xff0c;Memory分析功能尤其强大支持对jdbc,noSql,jsp,servlet,socket进行分析支持多种模式(离线、在线)的分析支持监控本地、远程JVM跨平台&#xff0c;拥…

Vue01-vue的简介

一、Vue是什么&#xff1f; 一套用于构建用户界面的渐进式javaScript框架。 构建用户界面&#xff1a; 渐进式&#xff1a; 目前Vue的地位&#xff1a;生态完善&#xff0c;国内前端工程师必备技能。 二、Vue的特点 一个XXX.vue就是一个组件&#xff0c;封装的概念&#xff0c…

2025 QS 世界大学排名公布,北大清华跻身全球前20

一年一度&#xff0c;2025 QS 世界大学排名公布&#xff01; QS&#xff08;Quacquarelli Symonds&#xff09;是唯一一个同时将就业能力与可持续发展纳入评价体系的排名。 继去年 2024 QS 排名因为“墨尔本超耶鲁&#xff0c;新南悉尼高清华”而荣登微博热搜之后&#xff0c…

小米路由器如何设置去广告功能,如何设置小米路由器的自定义Hosts(小米路由器如何去除小米广告、去除小米电视盒子开屏广告、视频广告)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 实现方案 📒📝 操作步骤📝 注意事项⚓️ 相关链接 ⚓️📖 介绍 📖 小米设备的广告一直是用户头疼的问题,无论是开屏广告、应用内广告还是系统广告,都影响了用户体验。本文将详细介绍如何通过小米路由器实现去除广告…

测试基础09:缺陷(bug)生命周期、定位方式和管理规范

课程大纲 1、缺陷&#xff08;bug&#xff09;生命周期 2、缺陷&#xff08;bug&#xff09;提交规范 2.1 宗旨 简洁、清晰、可视化&#xff0c;减少沟通成本。 2.2 bug格式和内容 ① 标题&#xff1a;一级功能-二级功能-三级功能_&#xff08;一句话描述bug&#xff1a;&…