热门标签 | 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内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • 本文详细探讨了Java中的24种设计模式及其应用,并介绍了七大面向对象设计原则。通过创建型、结构型和行为型模式的分类,帮助开发者更好地理解和应用这些模式,提升代码质量和可维护性。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • 作者:守望者1028链接:https:www.nowcoder.comdiscuss55353来源:牛客网面试高频题:校招过程中参考过牛客诸位大佬的面经,但是具体哪一块是参考谁的我 ... [详细]
  • 作为一名专业的Web前端工程师,掌握HTML和CSS的命名规范是至关重要的。良好的命名习惯不仅有助于提高代码的可读性和维护性,还能促进团队协作。本文将详细介绍Web前端开发中常用的HTML和CSS命名规范,并提供实用的建议。 ... [详细]
  • 网易严选Java开发面试:MySQL索引深度解析
    本文详细记录了网易严选Java开发岗位的面试经验,特别针对MySQL索引相关的技术问题进行了深入探讨。通过本文,读者可以了解面试官常问的索引问题及其背后的原理。 ... [详细]
  • 探索电路与系统的起源与发展
    本文回顾了电路与系统的发展历程,从电的早期发现到现代电子器件的应用。文章不仅涵盖了基础理论和关键发明,还探讨了这一学科对计算机、人工智能及物联网等领域的深远影响。 ... [详细]
  • 本文将介绍如何使用 Go 语言编写和运行一个简单的“Hello, World!”程序。内容涵盖开发环境配置、代码结构解析及执行步骤。 ... [详细]
  • 线性Kalman滤波器在多自由度车辆悬架主动控制中的应用研究
    本文探讨了线性Kalman滤波器(LKF)在不同自由度(2、4、7)的车辆悬架系统中进行主动控制的应用。通过详细的仿真分析,展示了LKF在提升悬架性能方面的潜力,并总结了调参过程中的关键要点。 ... [详细]
  • 本文探讨了Hive中内部表和外部表的区别及其在HDFS上的路径映射,详细解释了两者的创建、加载及删除操作,并提供了查看表详细信息的方法。通过对比这两种表类型,帮助读者理解如何更好地管理和保护数据。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • MQTT技术周报:硬件连接与协议解析
    本周开发笔记重点介绍了在新项目中使用MQTT协议进行硬件连接的技术细节,涵盖其特性、原理及实现步骤。 ... [详细]
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社区 版权所有