priority_queue的介绍及使用(18)

news2025/1/20 10:55:35

目录

1、priority_queue的介绍

2、priority_queue的使用

3、priority_queue的模拟实现

1、简单实现一个大堆的

2、带仿函数的

1、初识仿函数

2、priority_queue带仿函数版本

3、其他


1、priority_queue的介绍

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

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

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

4、底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭代器访问,并支持以下操作:

empty():检测容器是否为空

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

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

push_back():在容器尾部插入元素 

pop_back():删除容器尾部元素

5、标准容器类vector和deque满足这些需求。默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用vector。

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

2、priority_queue的使用

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

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

注:1、默认是大的优先级高——默认给的仿函数是less;控制小的优先级高——给一个greater仿函数,头文件在#include<functional>。

2、仿函数是一个自定义类型,是类模板。

3、sort默认是升序。

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

int main()
{
	//默认是大的优先级高——默认给的仿函数是less
	//控制小的优先级高——给一个greater仿函数,头文件在#include<functional>
	//priority_queue<int> pq;
	priority_queue<int,vector<int>,greater<int>> pq;
	pq.push(1);
	pq.push(6);
	pq.push(3);
	pq.push(4);

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

3、priority_queue的模拟实现

1、简单实现一个大堆的

1、PriorityQueue.h

#pragma once
#include<iostream>
#include<vector>
#include<assert.h>
using namespace std;

namespace tutu
{
	//建大堆
	template<class T,class Container=vector<T>>
	class priority_queue
	{
		void adjust_up(size_t child)
		{
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
				if (_con[child] > _con[parent])
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

		void adjust_down(size_t parent)
		{
			size_t child = parent * 2 + 1;
			while (child < _con.size())
			{
				if (child+1 < _con.size()&&_con[child + 1] > _con[child])
				{
					child++;
				}
				if (_con[child] > _con[parent])
				{
					swap(_con[child], _con[parent]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}
	public:
		priority_queue()
		{}

		template<class InputIterator>
		priority_queue(InputIterator first, InputIterator last)
			:_con(first,last)
		{
			//建堆
			for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--)
			{
				adjust_down(i);
			}
		}

		void push(const T& x)
		{
			_con.push_back(x);
			adjust_up(_con.size() - 1);
		}

		void pop()
		{
			assert(!_con.empty());
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			adjust_down(0);
		}

		bool empty()
		{
			return _con.empty();
		}

		const T& top()
		{
			return _con[0];
		}

		size_t size()
		{
			return _con.size();
		}

	private:
		Container _con;
	};

	void test1()
	{
		priority_queue<int, vector<int>> pq;
		pq.push(1);
		pq.push(2);
		pq.push(3);
		pq.push(4);
		pq.push(5);
		while (!pq.empty())
		{
			cout << pq.top() << " ";
			pq.pop();
		}
		cout << endl;
	}
}

2、test.cpp

#include"PriorityQueue.h"
int main()
{
	tutu::test1();
	return 0;
}

2、带仿函数的

1、初识仿函数

C++几乎抛弃了C语言中一些比较复杂的东西,例如:指针,几乎都用引用代替;函数指针、宏,都不建议使用了。仿函数是替代函数指针的一个方式。

仿函数:自定义类型像函数一样去使用,通过重载operator()。

例如:

#include<iostream>
using namespace std;

struct Less
{
	bool operator()(int x, int y)
	{
		return x < y;
	}
};

int main()
{
	Less less;
	cout << less(1, 2) << endl;
	return 0;
}

如果要支持任意类型比较,可以定义成模板类,如:

#include<iostream>
using namespace std;

template<class T>
struct Less
{
	bool operator()(const T& x, const T& y)
	{
		return x < y;
	}
};

int main()
{
	Less<int> less;
	cout << less(1, 2) << endl;
	//匿名对象
	cout << Less<int>()(2, 4) << endl;
	return 0;
}

2、priority_queue带仿函数版本

1、PriorityQueue.h

#pragma once
#include<iostream>
#include<vector>
#include<assert.h>
using namespace std;

namespace tutu
{
	template<class T>
	struct Greater
	{
		bool operator()(const T& x, const T& y) const
		{
			return x > y;
		}
	};

	template<class T>
	struct Less
	{
		bool operator()(const T& x, const T& y) const
		{
			return x < y;
		}
	};

	//建大堆
	template<class T,class Container=vector<T>,class Compare=Less<T>>
	class priority_queue
	{
		void adjust_up(size_t child)
		{
			Compare com;
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
				//if (_con[child] > _con[parent])
				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 child = parent * 2 + 1;
			while (child < _con.size())
			{
				//if (child+1 < _con.size()&&_con[child + 1] > _con[child])
				if(child + 1 < _con.size()&&com(_con[child], _con[child + 1]))
				{
					child++;
				}
				//if (_con[child] > _con[parent])
				if(com(_con[parent], _con[child]))
				{
					swap(_con[child], _con[parent]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}
	public:
		priority_queue()
		{}

		template<class InputIterator>
		priority_queue(InputIterator first, InputIterator last)
			:_con(first,last)
		{
			//建堆
			for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--)
			{
				adjust_down(i);
			}
		}

		void push(const T& x)
		{
			_con.push_back(x);
			adjust_up(_con.size() - 1);
		}

		void pop()
		{
			assert(!_con.empty());
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			adjust_down(0);
		}

		bool empty()
		{
			return _con.empty();
		}

		const T& top()
		{
			return _con[0];
		}

		size_t size()
		{
			return _con.size();
		}

	private:
		Container _con;
	};

	void test1()
	{
		priority_queue<int, vector<int>,Greater<int>> pq;
		pq.push(5);
		pq.push(4);
		pq.push(3);
		pq.push(2);
		pq.push(1);
		while (!pq.empty())
		{
			cout << pq.top() << " ";
			pq.pop();
		}
		cout << endl;
	}
}

2、test.cpp

#include"PriorityQueue.h"
int main()
{
	tutu::test1();
	return 0;
}

3、其他

如果上面实现的仿函数版本priority_queue中存Date类,那么可能会有问题。

解决方法:1、在Date中重载 >、< 的比较    2、自己写一个Date类专用的仿函数

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

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

相关文章

Unity 3D 物理引擎简介 || Unity 3D 物理材质|| Unity 3D 力(AddForce)

Unity 3D 物理引擎简介 早期的游戏并没有强调物理引擎的应用&#xff0c;当时无论是哪一种游戏&#xff0c;都是用极为简单的计算方式做出相应的运算就算完成物理表现&#xff0c;如超级玛丽和音速小子等游戏。 较为常见的物理处理是在跳跃之后再次落到地上&#xff0c;并没有…

百万级数据的导出解决方案

一、传统POI的的版本优缺点比较首先我们知道POI中我们最熟悉的莫过于WorkBook这样一个接口&#xff0c;我们的POI版本也在更新的同时对这个几口的实现类做了更新&#xff1b;HSSFWorkbook : 这个实现类是我们早期使用最多的对象&#xff0c;它可以操作Excel2003以前&#xff08…

SAP 系统内核版本详解

前言&#xff1a;之前两篇简单介绍了ABAP 7.40的新特性&#xff0c;那么有的时候会有这样的情况&#xff0c;根据新特性写代码的时候校验会不通过&#xff0c;这又是为啥呢&#xff1f;会不会跟SAP的版本有关系呢&#xff1f; 那么&#xff0c;首先我们就来看一下在SAP系统中如…

基于TC397的Bootloader开发过程中遇到的问题记录

问题11 现象&#xff1a;刷新流程结束之后上位机通过22服务AFFC读取刷新计数时&#xff0c;刷新计数会偶发地置12 分析思路&#xff1a;尝试用单步调试的方法复现该现象&#xff0c;程序中涉及到刷新计数的更新有两处&#xff0c;一是在34服务中擦flash前&#xff0c;二是在31服…

【数据结构】栈及其经典面试题详解

目录前言一、栈的介绍二、数据类型重定义三、栈的结构四、栈中的常见操作五、测试栈六、栈的常见面试题前言 前面学习的线性表中包含顺序表和链表&#xff0c;这两种数据结构允许在任意位置进行插入和删除&#xff0c;那么有没有一种数据结构是不能在任意位置进行插入删除&…

全面解读MinION纳米孔测序技术及应用

全面解读MinION纳米孔测序技术及应用 link&#xff1a;https://www.seqchina.cn/467.html 【测序中国】 paper&#xff1a;The Oxford Nanopore MinION: delivery of nanopore sequencing to the genomics community https://pubmed.ncbi.nlm.nih.gov/27887629/ 纳米孔测序技术…

知识蒸馏 Knowledge distillation(学习笔记)

知识蒸馏概述 蒸馏&#xff1a;把大的 复杂的东西变成小的纯净的东西 在知识蒸馏中 大的模型为 教师模型&#xff08;teacher&#xff09;臃肿 集成 牛逼 复杂的 小的 为 学生模型&#xff08;student&#xff09;小的精干的 轻量化的 这里有一个知识的迁移 因为落地实…

相关性模型与回归模型(例题代码)

一、相关性模型&#xff08;SPSS&#xff09; 相关性模型涉及到两种最为常用的相关系数&#xff1a; 皮尔逊person相关系数斯皮尔曼spearman等级相关系数 1、皮尔逊相关系数 相关性可视化 总结&#xff1a; 1.如果两个变量本身就是线性的关系&#xff0c;那么皮尔逊相关系…

儿子小伟再婚,新儿媳紧锁眉头,农民歌唱家大衣哥有些过分了

虽然都知道大衣哥儿子小伟结婚&#xff0c;这一天早晚都要到来&#xff0c;但是却没有想到来得那么快&#xff0c;大衣哥儿子小伟的婚礼&#xff0c;在悄无声息中结束了。说起大衣哥儿子小伟&#xff0c;这已经不是第一次结婚了&#xff0c;因为结过婚有经验&#xff0c;这一次…

Linux CFS调度器之pick_next_task函数

文章目录前言一、pick_next_task二、pick_next_task_fair参考资料前言 在内核执行__schedule函数&#xff0c;进程任务切换的时候&#xff0c;__schedule函数函数会调用pick_next_task让调度器从就绪队列中选择最合适的一个进程运行&#xff0c;如下所示&#xff1a; static …

Nerdctl 原生支持 Nydus 加速镜像

文&#xff5c;李楠&#xff08;GitHub ID : loheagn&#xff09; 北京航空航天大学 21 级研究生 云原生底层系统的开发和探索工作。 本文 6369 字 阅读 16 分钟 OSPP 开源之夏是由中科院软件研究所“开源软件供应链点亮计划”发起并长期支持的一项暑期开源活动。旨在鼓励在…

关于whl,你想知道的

一、whl是什么&#xff1f;whl文件时以wheel格式保存的python安装包&#xff0c;Wheel是Python发行版的标准内置包格式。WHL文件包含Python安装的所有文件和元数据&#xff0c;其中还包括所使用的Wheel版本和打包的规范。WHL文件使用Zip压缩进行压缩&#xff0c;实际上也是一种…

二、TCO/IP---Ethernet和IP协议

TCP/ip协议栈 OSI模型TCP/IP协议栈应用层&#xff0c;表示层&#xff0c;会话层应用层传输层主机到主机层&#xff08;传输层&#xff09;网络层网络层数据链路层&#xff0c;物理层网络接入层 Ethernet协议 以太网&#xff0c;实现链路层的数据传输和地址封装&#xff08;MA…

【Qt】Qt中的拖放操作实现——拖放文件以及自定义拖放操作

文章目录Qt的拖放操作使用拖放打开文件自定义拖放操作文章参考《Qt Creator快速入门&#xff08;第三版&#xff09;》。 Qt的拖放操作 拖放操作分为拖动Drag和放下Drop&#xff0c;Qt提供了强大的拖放机制&#xff0c;可在帮助文档中通过Drag and Drop关键字查看。 在Qt中&a…

ArcGIS基础实验操作100例--实验78按栅格分区统计路网

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验78 按栅格分区统计路网 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;…

【数据结构】队列详解

前言 前面我们学习了一种数据结构&#xff1a;栈&#xff0c;栈是一种只允许在一端尽进行插入删除的数据结构&#xff0c;而今天我们将学习另一种数据结构&#xff1a;队列&#xff0c;队列是一种支持在一端进行插入&#xff0c;在另一端进行删除的数据结构。 一、队列的介绍…

PHP反序列化字符串逃逸

PHP反序列化字符串逃逸 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录PHP反序列化字符串逃逸前言一、关于反序列化和序列化二、[0ctf 2016]unserialize二、prize_p5[NSSCTF]前言 例如&#xff1a;最近日常刷题玩…

常用的传输码介绍

文章目录前导知识1.AMI码2.HDB3码3.PST码4.数字双相码5.CMI码6.nBmB码前导知识 在介绍常用的传输码之前&#xff0c;先简单介绍一下直流分量。 信号的直流分量就是信号的平均值&#xff0c;它是一个与时间无关的常数&#xff0c;直流分量的数学公式表示为&#xff1a; 判断有…

基于轻量级YOLOv5+Transformer的汽车车损检测识别分析系统

将传统NLP领域提出来的Transformer技术与yolo目标检测模型融合已经成为一种经典的做法&#xff0c;早在之前的很多论文里面就有这种组合应用的出现了&#xff0c;本文主要是借鉴前文的思路&#xff0c;开发基于yolov5transformer的汽车车损检测识别模型&#xff0c;首先看下效果…

光流相关总结

基于图像亮度恒定假设&#xff0c; 图像亮度&#xff1a;I(x⃗,t)I(\vec x, t)I(x,t), 其中x⃗[x,y]\vec x[x,y]x[x,y]&#xff0c;那么亮度恒定假设&#xff1a; I(x⃗,t)I(x⃗δx⃗,tδt)(1)I(\vec x,t)I(\vec x \delta \vec x, t \delta t) (1)I(x,t)I(xδx,tδt)(1) 对上式…