【C++】优先级队列priority_queue/仿函数(函数对象)

news2024/10/6 10:42:47

这里写目录标题

  • 一.优先级队列
    • 1.优先级队列的介绍
    • 2.priority_queue的定义与使用
  • 二.仿函数/函数对象
  • 三.优先级队列的模拟实现

一.优先级队列

1.优先级队列的介绍

在这里插入图片描述

1)注意优先级队列和队列不是一个东西,队列是容器,优先级队列是一种容器适配器,不提供迭代器。(了解容器适配器,请点击这篇文章:【C++】容器适配器)

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

3)优先级队列:
less->大堆,默认优先级高的元素先输出;
greater->小堆,默认优先级小的元素先输出。

4)注意priority_queue默认构建大堆。原因:运行下面的代码,向堆中插入数据后,默认使用向上调整算法,构建大堆,我们依次取top(栈顶元素),输出的结果是降序,即优先级高的元素先输出。

对堆的数据结构还不熟悉或忘了的宝子们可以点击这篇博客进行学习——>【数据结构】堆的实现

在这里插入图片描述

2.priority_queue的定义与使用

priority_queue的各个成员函数及其功能如下:
在这里插入图片描述
方式一:不指定底层容器和内部需要构造的堆结构。(默认使用vector作为底层容器,构造大堆结构)

priority_queue<int> pq;

方式二:使用vector作为底层容器,内部构造大堆结构。

priority_queue<int,vector<int>,less<int>> pq1;

方式三:使用vector作为底层容器,内部构造小堆结构。[使用方式如下图]

priority_queue<int,vector<int>,greater<int>> pq2;

在这里插入图片描述

二.仿函数/函数对象

1.在C语言中,我们是用函数指针实现函数的传递。但是函数指针的形式有些累赘,那么C++引入了仿函数(又称函数对象)。
仿函数(函数对象)的定义:如果我们在一个类中重载了()运算符。那么该类的实例化对象就可以像调用函数一样去调用。具体实现过程的代码如下:

#include<iostream>
using namespace std;
//仿函数/函数对象
namespace nn
{
	template<class T>
	class less//<
	{
	public:
		bool operator()(const T& x, const T& y)
		{
			return x < y;
		}
	};
	template<class T>
	class greater//>
	{
	public:
		bool operator()(const T& x, const T& y)
		{
			return x > y;
		}
	};
}
//函数对象传参:需要定义多参数模板
template<class T,class Compare>
void bubble_sort(T* a, int n,Compare com)
{
	for (int i = 0; i < n-1; i++)
	{
		int flag = 0;
		for (int j = 1; j < n - i; j++)
		{
			if (com(a[j], a[j-1]))//com是类的实例化对象,com()相当于运算符重载函数,operator>,operator<
			{
				swap(a[j-1], a[j]);
				flag = 1;
			}
		}
		if (flag == 0)
		{
			break;
		}
	}
}
int main()
{
	nn::less<int> lessFunc;//我们在less类中重载了()运算符,就可以用该类的实例化对象当作函数来使用
	nn::greater<int> greaterFunc;//我们在less类中重载了()运算符,就可以用该类的实例化对象当作函数来使用
	int a[] = { 2, 3, 4, 5, 6, 1, 2, 4, 9 };
	bubble_sort(a, sizeof(a) / sizeof(a[0]), lessFunc);

	for (auto e : a)
	{
		cout << e << " ";
	}
	cout << endl;

	bubble_sort(a, sizeof(a) / sizeof(a[0]), greaterFunc);

	for (auto e : a)
	{
		cout << e << " ";
	}
	cout << endl;
	return 0;
}

2.上面的less和greater类是我们自己实现的,库中也有对应的类,头文件是functional,这里给个C++标准库less类的解释。

在这里插入图片描述

三.优先级队列的模拟实现

priority_queue的底层实际上是堆结构,实现priority_queue之前,我们得先知道堆这个数据结构的算法,详情请点击【数据结构】堆的实现

  • 升序建大堆——>小于号——>less
  • 降序建小堆——>大于号——>greater
#define _CRT_SECURE_NO_WARNINGS 1
namespace nn
{
	template<class T>
	class less//<
	{
	public:
		bool operator()(const T& x, const T& y)
		{
			return x < y;
		}
	};
	template<class T>
	class greater//>
	{
	public:
		bool operator()(const T& x, const T& y)
		{
			return x > y;
		}
	};
	//多参数模板:数据类型,容器,函数对象/仿函数
	template<class T, class Container = vector<T>,class Compare = less<T>>//优先级队列默认建大堆,less——>小于号
	class priority_queue
	{
	public:
		//构造函数
		priority_queue()
		{}
		//迭代器构造
		template<class InputIterator>
		priority_queue(InputIterator first, InputIterator last)
			:_con(first,last)
		{
			//向下调整建堆,时间复杂度O(N)
			for (size_t i = (_con.size() - 1 - 1) / 2; i >= 0; i--)
			{
				adjust_down(i);
			}
		}
		
		void adjust_up(size_t child)
		{
			Compare com;//定义一个仿函数对象,可以用作函数
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
				//if (_con[parent] < _con[child])
				if(com(_con[parent],_con[child]))
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}
		void adjust_down(size_t parent)
		{
			Compare com;

			size_t minchild = parent * 2 + 1;
			while (minchild < _con.size())
			{
				if (minchild + 1 < _con.size() && com(_con[minchild],_con[minchild + 1]))
				{
					minchild = minchild + 1;
				}
				//if (_con[parent] < _con[minchild])
				if(com(_con[parent],_con[minchild]))
				{
					swap(_con[minchild], _con[parent]);
					parent = minchild;
					minchild = 2 * parent + 1;
				}
				else
				{
					break;
				}
			}
		}
		//一边push一边向上调整
		void push(const T& x)
		{
			_con.push_back(x);
			adjust_up(_con.size() - 1);
		}
		//pop的是栈顶元素,交换栈顶元素和最后一个元素,删除最后一个元素,然后用向下调整算法(时间复杂度logN,因为已经满足左右子树是堆,所以可以直接用向下调整算法)
		void pop()
		{
			swap(_con[0],_con[_con.size() - 1]);
			_con.pop_back();
			adjust_down(0);
		}
		const T& top() const
		{
			return _con[0];
		}
		size_t size() const
		{
			return _con.size();
		}
		bool empty() const
		{
			return _con.empty();
		}

	private:
		Container _con;
	};
}

如果在priority_queue中放自定义类型的数据,用户需要在自定义类型中提供>,<的运算符重载。

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
		:_year(year)
		,_month(month)
		,_day(day)
	{}
	//自定义类需要自己重载>,<等运算符
	bool operator<(const Date& d) const
	{
		return (_year < d._year) ||
			(_year == d._year && _month < d._month) ||
			(_year == d._year && _month == d._month && _day < d._day);
	}
	bool operator>(const Date& d)const
	{
		return (_year > d._year) ||
			(_year == d._year && _month > d._month) ||
			(_year == d._year && _month == d._month && _day > d._day);
	}
	friend ostream& operator<<(ostream& _cout, const Date& d)
	{
		_cout << d._year << "-" << d._month << "-" << d._day;
		return _cout;
	}
private:
	int _year;
	int _month;
	int _day;
};

//对Date*重载两个类
struct PDateLess
{
	bool operator()(const Date* x, const Date* y)
	{
		return *x < *y;
	}
};
struct PDateGreater
{
	bool operator()(const Date* x, const Date* y)
	{
		return *x > *y;
	}
};
void TestPriorityQueue()
{
	// 大堆,需要用户在自定义类型中提供<的重载
	priority_queue<Date> q1;
	q1.push(Date(2018, 10, 29));//匿名对象
	q1.push(Date(2018, 10, 28));
	q1.push(Date(2018, 10, 30));
	cout << q1.top() << endl;

	// 如果要创建小堆,需要用户提供>的重载
	priority_queue<Date, vector<Date>, greater<Date>> q2;
	q2.push(Date(2018, 10, 29));
	q2.push(Date(2018, 10, 28));
	q2.push(Date(2018, 10, 30));
	cout << q2.top() << endl;

	//那如果改成传日期对象的地址呢?
	//答:重新重载两个类比较日期的大小
	priority_queue<Date*, vector<Date*>, PDateLess> q3;
	q3.push(new Date(2018, 10, 29));//匿名对象,new返回的是动态开辟空间的地址
	q3.push(new Date(2018, 10, 28));
	q3.push(new Date(2018, 10, 30));
	cout << *q3.top() << endl;

	priority_queue<Date*, vector<Date*>, PDateGreater> q4;
	q4.push(new Date(2018, 10, 29));
	q4.push(new Date(2018, 10, 28));
	q4.push(new Date(2018, 10, 30));
	cout << *q4.top() << endl;
}

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

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

相关文章

服务监控之promethues+grafana,直接送你上大师,这还不上热门吗

最近的项目需要上监控&#xff0c;虽然之前也是使用这个方案&#xff0c;但是作为使用者一直没有太关注细节&#xff0c;也没有真正的去部署过&#xff0c;刚好凑着这次机会&#xff0c;彻底掌握下这套监控系统 1、监控系统架构 监控的架构这个图几乎每个文章都有&#xff0c…

学习JS,实现自动打字机动效

前几天遇到一个需求&#xff0c;产品告诉我说&#xff0c;希望这些字可以像自动打字那样&#xff0c;一个一个的出来&#xff0c;于是在完成需求的同时&#xff0c;顺便把这个方法记录出来&#xff0c;看大家是否也需要。 目录 1、实现思路 2、html布局和css样式 3、预定义…

【数据库】什么是关系型数据库和非关系型数据库

数据库分类关系型数据库非关系型数据库键值对存储数据库列存储数据库搜索引擎数据库面向文档数据库图形数据库数据库优缺点应用程序都离不开数据库&#xff0c;那不同的数据结构&#xff0c;就会存放在不同的数据数据库中&#xff0c;所以数据库按数据结构分为关系型数据库和非…

spring事务失效的一些场景

1、 Transactional 只能作用在public修饰的方法上 spring事务的实现AbstractFallbackTransactionAttributeSource类的computeTransactionAttribute方法中有个判断&#xff0c;如果目标方法不是public&#xff0c;则TransactionAttribute返回null&#xff0c;即不支持事务。 2…

ORB-SLAM3算法和代码学习——跟踪参考关键帧TrackReferenceKeyFrame

0总述 无论是跟踪恒速运动模型还是跟踪参考关键帧&#xff0c;本质上都是基于帧间匹配跟踪。 跟踪恒速模型是当前帧和上一帧之间的匹配&#xff0c;使用基于恒速模型计算得到的位姿作为优化的初始位姿&#xff0c;基于网格和搜索半径寻找匹配关系。 跟踪参考关键帧是当前帧和…

SpringCloudAlibabaSentinel实现网关动态限流

目录 1.SpringCloudAlibabaSentinel实现网关动态限流 1.概念和来历 2.概览及控制台搭建 3.控制台有哪些能力 4.功能及设计理念 5.限流的几种方法 2.SpringCloud Alibaba Sentinel 的降级功能 1.yml中添加配置 2.编写配置类 3.编写兜底工具类 3.Sentinel还对Feigin实…

代码整洁之道,好的代码就是为了更美好的生活

概述 美国童子军有一条简单的军规&#xff1a;让营地比你来时更干净。当梳理代码时&#xff0c;坚守此军规&#xff1a;每次 review 代码&#xff0c;让代码比你发现它时更整洁。 一位大神说过&#xff1a;“衡量代码质量的唯一有效标准&#xff1a;WTF/min”&#xff0c;并配…

14.Isaac教程--Jetbot应用示例

Jetbot应用示例 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 本节介绍如何将 Isaac SDK 与 NVIDIA 新的高性能模拟平台 Omniverse 集成&#xff0c;以让 Jetbot 在模拟中跟随球。 本节作为使用三个 Jetbot 应用程序进入 Omniverse 和 Isaac …

国产的蓝光存储设备能算信创产品吗?

这个问题是客户前几天问我的&#xff0c;笔者只能实事求是的告诉他&#xff1a;目前还不能算&#xff01;首先蓝光存储产品暂时未被列入信创名录&#xff0c;其次蓝光存储中最核心的读写设备&#xff08;蓝光光驱&#xff09;的技术专利和生产工艺基本被日本企业&#xff08;索…

LeetCode 101. 对称二叉树

&#x1f308;&#x1f308;&#x1f604;&#x1f604; 欢迎来到茶色岛独家岛屿&#xff0c;本期将为大家揭晓LeetCode 101. 对称二叉树&#xff0c;做好准备了么&#xff0c;那么开始吧。 &#x1f332;&#x1f332;&#x1f434;&#x1f434; 一、题目名称 LeetCode 1…

高端运动耳机哪个品牌最好、公认最好的跑步耳机品牌排名

在健身、运动的时候&#xff0c;过程往往是很枯燥的&#xff0c;这时候&#xff0c;如果能有动感的音乐在旁&#xff0c;调动我们的积极性&#xff0c;就再好不过了&#xff0c;所以很多人在运动的时候都会选择佩戴一款运动蓝牙耳机。不过适合运动的蓝牙耳机少之又少&#xff0…

七、MySQL 多表查询详解(附练习题及答案----超详细)

文章目录一、笛卡尔积&#xff08;或交叉连接&#xff09;的理解二、多表查询分类讲解2.1 分类1&#xff1a;等值连接 vs 非等值连接2.2 分类2&#xff1a;自连接 vs 非自连接2.3 分类3&#xff1a;内连接 vs 外连接2.4 SQL99语法实现多表查询2.4.1 内连接2.4.2 左连接2.4.3 右…

System Description 步骤

纲要&#xff1a; 在有了Composition以后&#xff0c;下一步就是把它分配到ECU里面。 1. Create System Description Import DBC file, select ECUs and CAN Frames under the DBC. Then it will create "SystemDescription.arxml" file. [1] 2. Check the content…

地图下载器代码结构设计及功能实现

jcef包引入表结构设计后台关键代码结构前端关键代码结构功能展示启动页底图切换绘制选择下载区域行政区划切换选择下载区域下载关键代码import { InnerMqClient } from ../../rx/inner-mq.service;import { SubmitService } from ../../service/submit.service;import { MapBas…

马蹄集 字符判断

字符判断 难度&#xff1a;白银 时间限制&#xff1a;1秒 巴占用内存&#xff1a;64M 输入一个字符&#xff0c;判断是数字字符、大写字母、小写字母、算术运算符、 关系运算符、逻辑运算符&#xff0c;还是其他字符&#xff0c;分别输出Number?”, "Capital letter?”,…

Springboot集成knife4j文档时,接口信息没有显示

我使用的 SpringBoot、knife4j 版本jar包如下所示&#xff1a;<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.5.RELEASE</version><relativePath/> …

kube-bench初体验

kube-bench是一个通过运行CIS Kubernetes benchmark中记录的checker来检查Kubernetes是否安全部署的工具。测试&#xff0c;找gap&#xff0c;audit&#xff0c;都可以啊关于CIS k8s benchmark 参见 CIS Kubernetes Benchmarks (cisecurity.org)就是说&#xff0c;想做k8s加固&…

再学C语言32:函数——多源代码文件程序及其编译

使用多个函数时&#xff0c;最简单的方法是将所有函数放在同一文件中&#xff0c;就像编译单个函数的文件一样对该文件进行编译 具体的编译过程根据操作系统不同而具有差异性 Window系统下的编译器是面向工程的 工程&#xff08;project&#xff09;&#xff1a;描述了一个特…

【Linux】项目自动化构建工具—make/makefile

文章目录1. 什么是make/makefile&#xff1f;2. make/makefile的使用2.1 实例代码2.2 依赖关系和依赖方法2.3 项目清理2.4 make是如何确定是否编译的3. Linux第一个小程序—进度条3.1 \r 和 \n3.2 进度条小程序1. 什么是make/makefile&#xff1f; make是一个命令工具&#xf…

【Spring6源码・IOC】Bean的初始化 - 终结篇

前面两篇&#xff0c;我们着重讲解了一下《BeanDefinition的加载》和《bean的实例化》。 这一篇我们来讲解一下bean的初始化。 我们这里的案例依旧是以SpringBoot3.0、JDK17为前提&#xff0c;案例代码如下&#xff1a; Component public class A {Autowiredprivate B b;}Com…