【C++/STL】:优先级队列的使用及底层剖析仿函数

news2024/11/25 10:42:46

目录

  • 💡前言
  • 一,优先级队列的使用
  • 二,仿函数
    • 1,什么是仿函数
    • 2,仿函数的简单示例
  • 三,优先级队列的底层剖析

💡前言

优先队列(priority_queue)是一种容器适配器,默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。注意:默认情况下priority_queue是大堆

注意:使用优先级队列要包含头文件 < queue >

一,优先级队列的使用

在这里插入图片描述

代码实现如下:

这里的建堆一般有两种方式:
(1) 一种是一个一个push进vector容器再进行向上调整建堆
(2) 另一种是直接用迭代器区间构造直接建堆(推荐用这种)

#include <iostream>
#include <queue>
#include <functional>
using namespace std;

void test_priority_queue()
{
	vector<int> v = { 6,0,3,5,4,7,9,1,2,8 };

	//默认升序
	//priority_queue<int> pq(v.begin(), v.end());

	//一个一个尾插建堆
	priority_queue<int, vector<int>, greater<int>> pq;
	for (auto e : v)
	{
		pq.push(e);
	}

	//迭代器区间构造,直接建堆
	//priority_queue<int,vector<int>,greater<int>> pq(v.begin(), v.end());

	while (!pq.empty())
	{
		cout << pq.top() << " ";
		pq.pop();
	}
	cout << endl;

}

int main()
{
	test_priority_queue();

	return 0;
}

注意:优先级队列默认的大堆,降序排列,如果要升序,就要换仿函数。下图中第三个模板参数就是传仿函数。

使用算法库里的 less 和 greater 算法,需要包含头文件< functional >

在这里插入图片描述

二,仿函数

1,什么是仿函数

仿函数也叫函数对象,是一个重载了 operator() 的类,可以使得类的对象像函数一样使用

2,仿函数的简单示例

operator()并没有参数的个数和返回值,所以使用是十分灵活的

struct Func1
{
	//无参无返回值
	void operator()()
	{
		cout << "Func调用" << endl;
	}
};

struct Func2
{
	//有参无返回值
	void operator()(int n)
	{
		while (n--)
		{
			cout << "Func调用" << endl;
		}
	}
};

int main()
{
	Func1 f1;
	f1();  //使得对象像函数一样使用
	f1.operator()(); //显示调用

	cout << endl;

	Func2 f2;
	f2(3);  //使得对象像函数一样使用

	return 0;
}

在这里插入图片描述

三,优先级队列的底层剖析

namespace ling
{
	template<class T>
	class myless
	{
	public:
	    bool operator()(const T& x, const T& y)
	    {
	        return x < y;
	    }
	};
	
	template<class T>
	class mygreater
	{
	public:
	    bool operator()(const T& x, const T& y)
	    {
	        return x > y;
	    }
	};
	
	template <class T, class Container = vector<T>, class Compare = myless<T>>
	class priority_queue
	{
	public:
	    priority_queue() = default;
		
		//迭代器区间构造
	    template <class InputIterator>
	    priority_queue(InputIterator first, InputIterator last)
	    {
	        while (first != last)
	        {
	            con.push_back(*first);
	            ++first;
	        }
	        //建堆
	        for (int i = (con.size() - 1 - 1) / 2; i >= 0; i--)
	        {
	            Adjust_down(i);
	        }
	    }
	
	    bool empty() const
	    {
	        return con.empty();
	    }
	
	    size_t size() const
	    {
	        return con.size();
	    }
		
		// 堆顶元素不允许修改,因为:堆顶元素修改可以会破坏堆的特性
	    const T& top()const
	    {
	        return con[0];
	    }
	
	    //向上调整
	    void Adjust_up(int child)
	    {
	        int parent = (child - 1) / 2;
	        while (child > 0)
	        {
	            //if (con[parent] < con[child])
	            if(comp(con[parent], con[child]))
	            {
	                swap(con[parent], con[child]);
	                child = parent;
	                parent = (child - 1) / 2;
	            }
	            else
	            {
	                break;
	            }
	        }
	    }
	
	    void push(const T& x)
	    {
	        con.push_back(x);
	        Adjust_up(con.size() - 1);
	    }
	
	    //向下调整
	    void Adjust_down(int parent)
	    {
	        int child = parent * 2 + 1;
	        while (child < con.size())
	        {
	            if (child + 1 < con.size() && comp(con[child], con[child + 1]))
	            {
	                child += 1;
	            }
	            //if (con[parent] < con[child])
	            if(comp(con[parent], con[child]))
	            {
	                swap(con[parent], con[child]);
	                parent = child;
	                child = parent * 2 + 1;
	            }
	            else
	            {
	                break;
	            }
	        }
	    }
	
	    void pop()
	    {
	        swap(con[0], con[con.size() - 1]);
	        con.pop_back();
	
	        Adjust_down(0);
	    }
	private:
	    Container con;
	    Compare comp;
	};
}

测试代码

void TestQueuePriority()
{
	ling::priority_queue<int> q1;
	q1.push(5);
	q1.push(1);
	q1.push(4);
	q1.push(2);
	q1.push(3);
	q1.push(6);
	cout << q1.top() << endl;

	q1.pop();
	q1.pop();
	cout << q1.top() << endl;

	vector<int> v{ 5,1,4,2,3,6 };
	ling::priority_queue<int, vector<int>, ling::greater<int>> q2(v.begin(), v.end());
	cout << q2.top() << endl;

	q2.pop();
	q2.pop();
	cout << q2.top() << endl;
}

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

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

相关文章

热点观察 | 《姜饼人王国》新作来袭、《Monopoly GO!》荣登5月全球畅销榜榜首

本周出海热点&#xff1a; 1. 中国品牌借欧洲杯打响知名度 2. 米哈游玩家切割二次元 3. 6月27日&#xff0c;Steam游戏《六月衷曲》上线TapTap 4. 《Monopoly GO!》荣登5月全球畅销榜榜首 5. 《地下城与勇士》拿下本周亚洲T1市场畅销榜冠军 6. 《姜饼人王国》新作强势登顶…

MySQL基础查询与复杂查询

基础查询 1、查询用户信息&#xff0c;仅显示用户的姓名与手机号&#xff0c;用中文显示列名。中文显示姓名列与手机号列。 2、根据商品名称进行模糊查询&#xff0c;模糊查询需要可以走索引&#xff0c;需要给出explain语句。使用explain测试给出的查询语句&#xff0c;需要显…

高中数学:复数-三角表示式

一、定义 辐角主值 二、复数乘除运算的三角表示及其几何意义 乘法 复数乘法的几何意义 除法 练习 解

Linux自动化交互脚本expect开发

在日常开发任务中&#xff0c;运行shell脚本有时候会提示输入密码的操作&#xff0c;如何让脚本自动输入密码呢&#xff1f;这时使用expect帮我们输入&#xff0c;Expect是基于Tcl发展而来的&#xff0c;它不仅可以进行交互&#xff0c;还可以根据程序的提示模拟标准输入&#…

AI原力觉醒:华硕NUC组团出道,快来Pick属于你的NUC

NUC 家族组团出道&#xff0c;全新的计算体验&#xff0c;重新定义桌面设备。AI加持下&#xff0c;谁最适合你&#xff1f; 颜值担当 NUC 14 Pro 居家必备单品 适用于广大消费者的NUC 14 Pro&#xff0c;不仅颜值在线&#xff0c;更多方位考虑您的日常所需&#xff0c;工作娱…

项目测试计划(Word)

1简介 1.1 目的 1.2 范围 2. 测试参考文档和测试提交文档 2.1 测试参考文档 2.2 测试提交文档 3. 测试策略 3.1整体测试策略 3.2功能测试 3.3 界面测试 3.4 性能测试 3.5 安全性测试 3.6 工具 4 测试阶段进入和退出标准 4.1进入标准 4.2退出标准 5 测试范围 5.1需要测试的模块 …

AirTestIDEA 使用windows窗口连接,切窗口后无法再操作已连接的游戏画面

目录 左上角&#xff1a; 选项 - 设置 - Windows窗口无嵌入链接(勾选)&#xff0c; 再使用 Windows窗口连接&#xff0c;中的"选择游戏画面"&#xff0c;可解决

【高等数学】一元函数积分及其应用:定积分与反常积分

文章目录 第一节. 定积分一. 定积分的概念1. 定义2. 定积分存在定理3. 定积分的几何意义与求解 二. 定积分的性质1. 不等式2. 中值定理 三. 积分上限&#xff08;为x&#xff09;函数1. 积分上限函数定义2. 积分函数求导3. 积分函数的奇偶性变化 四. 定积分的计算 第二节. 反常…

真实案例解析!企业如何做好安全生产管理工作?

很多企业都有相对应的安全管理制度&#xff0c;安全管理系统&#xff0c;安全管理人员等等&#xff0c;但这都仅限于企业“做了”安全生产管理&#xff0c;并不能“做好”安全生产管理。其实做好安全生产管理需要安全管理系统的配合。 听说过EHS系统吗&#xff1f;这系统能帮企…

【Android】在App里面安装Apk文件

项目需求 在一个App里面内置一个第三方的APK文件&#xff0c;然后通过这个App可以安装这个APK文件。 需求实现 1.内置APK文件 在App里面创建一个assets文件夹&#xff0c;然后把想要安装的APK文件放到这里面。 2.定义文件路径访问权限 创建一个文件&#xff0c;命名【file…

springboot系列七: Lombok注解,Spring Initializr,yaml语法

老韩学生 LombokLombok介绍Lombok常用注解Lombok应用实例代码实现idea安装lombok插件 Spring InitializrSpring Initializr介绍Spring Initializr使用演示需求说明方式1: IDEA创建方式2: start.spring.io创建 注意事项和说明 yaml语法yaml介绍使用文档yaml基本语法数据类型字面…

酣客的“FFC模式”|白酒商业模式|分润制度顶层架构设计

酣客公社摒弃传统商业模式&#xff0c;提出“心联网”及“FFC模式”的商业模式。 坐标&#xff1a;厦门&#xff0c;我是肖琳 深耕社交新零售行业10年&#xff0c;主要提供新零售系统工具及顶层商业模式设计、全案策划运营陪跑等。 今天和大家分享“酣客”的营销模式&#xff…

leetcode 动态规划(基础版)单词拆分

题目&#xff1a; 题解&#xff1a; 一种可行的dp做法是基于完全背包问题&#xff0c;将s看成是一个背包&#xff0c;wordDict看作是物品&#xff0c;然后往s中放入物品判断最终是否可以变为给定的s即可。这道题和上一题都用到了在dp如何枚举连续子串和状态表示&#xff1a;枚…

JavaWeb——MySQL

目录 2. 数据库设计 3. 表的关系 4. 表关系的实现 5. 多表查询 5.1 内连接 &#xff08;1&#xff09;隐式内连接 &#xff08;2&#xff09;显式内连接 ​5.2 外连接 &#xff08;1&#xff09;左外连接 &#xff08;2&#xff09;右外连接 2. 数据库设计 数据库设…

Eureka 服务注册与发现

目录 前言 注册中心 CAP 理论 常⻅的注册中心 CAP理论对比 Eureka 搭建 Eureka Server 引⼊ eureka-server 依赖 完善启动类 编写配置⽂件 启动服务 服务注册 引⼊ eureka-client 依赖 完善配置⽂件 启动服务 服务发现 引⼊依赖 完善配置⽂件 远程调⽤ 启动…

光明致优尊耀呈现“柏林爱乐在上海”音乐会正式开幕,奏响盛夏狂热乐章

2024年6月26日&#xff0c;由光明致优尊耀呈现的中国上海国际艺术节特别项目“柏林爱乐在上海”音乐会正式开幕。暌违七年&#xff0c;世界顶级交响乐团——柏林爱乐乐团再度访沪&#xff0c;在首席指挥基里尔别特连科率领下&#xff0c;正式在中国上海国际艺术节登台演出&…

Zynq MPSoC / RFSoC 动态配置 DIMM DDR

目录 名词释义硬软件版本Zynq MPSoC / RFSoC 动态 DDR 配置简介具体操作方法PCW GUI 配置启用动态 DDR 配置功能I2C 硬件要求根据硬件修改 FSBL初始化 I2C 控制器选择 I2C Mux 的 Slave读取 EEPROM 的第一页读取 EEPROM 的第二页 调试参考文档 本文首发于 Josh Gao 的博客&…

自动化测试小技巧之Airtest-Selenium和Excel的无缝协作

一、前言 之前在问卷以及Q群上有同学有提出过能否将网页上的一些数据通过Airtest去导出生成一份Excel&#xff0c;那么我们今天一起讨论一下&#xff0c;我们应该如何去实现&#xff0c;以及当我们获取的数据类型不同的时候&#xff0c;获取的方式该怎么随之调整&#xff1f; …

实现在父盒子中点击生成子盒子并识别父盒子边界不溢出

效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</…

高级运维工程师讲述银河麒麟V10SP1服务器加固删除snmp服务引起keeplived莫名连带删除引起生产事故实战

高级运维工程师讲述银河麒麟V10SP1服务器加固删除snmp服务引起keeplived莫名连带删除引起生产事故实战 一、核实操作系统信息 uname -a Linux localhost.localdomain 4.19.90-23.8.v2101.ky10.x86_64 #1 SMP Mon May 17 17:08:34 CST 2021 x86_64 x86_64 x86_64 GNU/Linuxcat…