热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

C++容器适配器priority_queue的使用及实现代码

这篇文章主要介绍了C++容器适配器priority_queue的使用及实现,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

优先级队列(Priority Queue)

队列是一种特征为FIFO的数据结构,每次从队列中取出的是最早加入队列中的元素。但是,许多应用需要另一种队列,每次从队列中取出的应是具有最高优先权的元素,这种队列就是优先级队列(Priority Queue),也称为优先权队列

1. 优先级队列的概念

优先级队列的定义

优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。

优先级队列的特点

  •  优先级队列是0个或多个元素的集合,每个元素都有一个优先权或值。
  • 当给每个元素分配一个数字来标记其优先级时,可设较小的数字具有较高的优先级,这样更方便地在一个集合中访问优先级最高的元素,并对其进行查找和删除操作。
  • 对优先级队列,执行的操作主要有:(1)查找,(2)插入,(3)删除。
  • 在最小优先级队列(min Priority Queue)中,查找操作用来搜索优先权最小的元素,删除操作用来删除该元素。
  • 在最大优先级队列(max Priority Queue)中,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素。
  • 插入操作均只是简单地把一个新的元素加入到队列中。
  • 注:每个元素的优先级根据问题的要求而定。当从优先级队列中删除一个元素时,可能出现多个元素具有相同的优先权。在这种情况下,把这些具有相同优先权的元素视为一个先来先服务的队列,按他们的入队顺序进行先后处理。

 2.优先级队列的使用

头文件:#include
优先级队列默认是最大优先级队列

接口介绍

函数声明 函数说明
priority_queue() / priority_queue(first, last) 构造一个空的优先级队列
empty( ) 判断优先级队列是否为空,为空返回true
empty( ) 判断优先级队列是否为空,为空返回true
top( ) 获取优先级队列中最大或者最小的元素,即堆顶元素
push(x) 将x元素插入到优先级队列中
pop() 删除优先级队列中最大或者最小的元素, 即删除堆顶元素

测试代码:

void test()
{
	priority_queue pq;
	pq.push(13);
	pq.push(14);
	pq.push(9);
	pq.push(23);
	pq.push(12);
	pq.push(22);
	while (!pq.empty())
	{
		cout <

测试结果:默认是最大优先级队列,所以堆顶元素一直是最大的元素

在这里插入图片描述

如何将创建最小优先级队列----
优先级队列原型:
泛型介绍T为优先级队列存储的数据类型;Container为优先级队列中存储数据的容器;Compare伪函数,决定是最大优先级队列还是最小优先级队列

template ,
  class Compare = less > class priority_queue;

创建最小优先级队列:

priority_queue, greater> pq;

测试结果:

在这里插入图片描述

优先级队列存放自定义类型时,需要自定义类型支持比较的操作。

class A
{
public:
	A(int a = 1)
		:_a(a)
	{}

	//支持比较函数
	bool operator<(const A& a) const
	{
		return _a (const A& a) const
	{
		return _a > a._a;
	}
	int _a;
};

测试结果:

在这里插入图片描述

在这里插入图片描述

应用场景:Top-K问题
数组中的第K个最大元素
代码:

class Solution {
public:
    int findKthLargest(vector& nums, int k) 
    {
        priority_queue pq(nums.begin(), nums.end());
        while (--k)
            pq.pop();
        return pq.top();
    }
};

3.优先级队列的实现

标准容器类vector和deque(双端队列)满足实现优先级队列的需求,库中底层默认是使用Vector容器来实现的,我们现在就利用vector简单模拟实现

private:
	vector con;

向下调整算法

向下调整算法用于优先级队列的删除接口的实现

void shiftDown()
	{
		int parent = 0;
		int child = 2 * parent + 1;
		while (child 

向上调整算法

向上调整算法用于优先级队列的插入接口的实现

//向上调整
	void shiftUp(int child)
	{
		int parent = (child - 1) / 2;
		while (child > 0)
		{
			if (con[parent] 

push()

  1. 将数据插入到容器的尾端
  2. 进行向上调整算法,建成堆
	void push(const T& val)
	{
		//尾插
		con.push_back(val);
		shiftUp(con.size() - 1);
	}

pop()

  • 将收尾数据进行交换
  • 删除末尾最后一个元素
  • 进行向下调整算法,建成堆
	void pop()
	{
		//交换
		swap(con[0], con[con.size() - 1]);
		con.pop_back();
		shiftDown();
	}

top()、size()、empty()

都直接使用容器中的接口实现

T& top()
	{
		return con.front();
	}

	size_t size() const
	{
		return con.size();
	}

	bool empty() const
	{
		return con.empty();
	}

测试结果:

在这里插入图片描述

但是我们的实现非常的死板,首先是不能创建最小优先级队列,其次是不能像底层实现一样,可以选择多种容器来存储数据来实现。

解决普通的优先级队列的两个问题

解决只能通过vector来存储数据的问题
我们可以通过容器多添加一个泛型来解决多种容器的存储
priority_queue可以通过 vector、deque实现
默认使用vector
原因:

  • list不支持随机访问迭代器的方式来访问元素
  • 与deque相比:deque随机访问效率低于vector

与之前代码需要修改的地方
1、泛型

template>

2、所需要的容器

private:
	Container con;

在这里插入图片描述

解决只能创建最大优先级队列问题
解决办法,加入新的泛型,该泛型是一个伪函数
如果不知道什么是伪函数,可以看看什么是伪函数,以及伪函数的使用
大小堆创建的不同其实就是在实现向上调整和向下调整时元素比较的不同而已。

与之前代码需要修改的地方
1、需要创建两个仿函数类

//用大最小优先级队列
template
struct Less
{
	bool operator()(const T& a, const T& b)
	{
		return a 
struct Greater
{
	bool operator()(const T& a, const T& b)
	{
		return a > b;
	}
};

2、加入新泛型

template, class Compare = Less>
private:
	Compare cmp;

3、利用仿函数,替代代码中关键的比较的地方

在这里插入图片描述
在这里插入图片描述

测试结果:

在这里插入图片描述
在这里插入图片描述

完整代码

//用大最小优先级队列
template
struct Less
{
	bool operator()(const T& a, const T& b)
	{
		return a 
struct Greater
{
	bool operator()(const T& a, const T& b)
	{
		return a > b;
	}
};

template, class Compare = Less>
class PriorityQueue
{
public:
	//向下调整
	void shiftDown()
	{
		int parent = 0;
		int child = 2 * parent + 1;
		while (child  0)
		{
			if (cmp(con[parent], con[child]))
			{
				swap(con[parent], con[child]);
				child = parent;
				parent = (child - 1) / 2;
			}
			else
			{
				break;
			}
		}
	}

	void push(const T& val)
	{
		//尾插
		con.push_back(val);
		shiftUp(con.size() - 1);
	}

	void pop()
	{
		//交换
		swap(con[0], con[con.size() - 1]);
		con.pop_back();
		shiftDown();
	}

	T& top()
	{
		return con.front();
	}

	size_t size() const
	{
		return con.size();
	}

	bool empty() const
	{
		return con.empty();
	}
private:
	Container con;
	Compare cmp;
};

到此这篇关于C++ 容器适配器priority_queue的使用及实现的文章就介绍到这了,更多相关C++ 容器适配器priority_queue内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • 本文介绍了Java的集合及其实现类,包括数据结构、抽象类和具体实现类的关系,详细介绍了List接口及其实现类ArrayList的基本操作和特点。文章通过提供相关参考文档和链接,帮助读者更好地理解和使用Java的集合类。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 近年来,大数据成为互联网世界的新宠儿,被列入阿里巴巴、谷歌等公司的战略规划中,也在政府报告中频繁提及。据《大数据人才报告》显示,目前全国大数据人才仅46万,未来3-5年将出现高达150万的人才缺口。根据领英报告,数据剖析人才供应指数最低,且跳槽速度最快。中国商业结合会数据剖析专业委员会统计显示,未来中国基础性数据剖析人才缺口将高达1400万。目前BAT企业中,60%以上的招聘职位都是针对大数据人才的。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • qt学习(六)数据库注册用户的实现方法
    本文介绍了在qt学习中实现数据库注册用户的方法,包括登录按钮按下后出现注册页面、账号可用性判断、密码格式判断、邮箱格式判断等步骤。具体实现过程包括UI设计、数据库的创建和各个模块调用数据内容。 ... [详细]
  • 如何使用计算机控制遥控车的步骤和电路制作方法
    本文介绍了使用计算机控制遥控车的步骤和电路制作方法。首先,需要检查发送器的连接器和跳线,以确定命令的传递方式。然后,通过连接跳线和地面,将发送器与电池的负极连接,以实现遥控车的前进。接下来,制作一个简单的电路,使用Arduino命令将连接到跳线的电线接地,从而实现将Arduino命令转化为发送器命令。最后,通过焊接晶体管和电阻,完成电路制作。详细的步骤和材料使用方法将在正文中介绍。 ... [详细]
author-avatar
幸福-一路向南_654
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有