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


推荐阅读
  • 兆芯X86 CPU架构的演进与现状(国产CPU系列)
    本文详细介绍了兆芯X86 CPU架构的发展历程,从公司成立背景到关键技术授权,再到具体芯片架构的演进,全面解析了兆芯在国产CPU领域的贡献与挑战。 ... [详细]
  • 双指针法在链表问题中应用广泛,能够高效解决多种经典问题,如合并两个有序链表、合并多个有序链表、查找倒数第k个节点等。本文将详细介绍这些应用场景及其解决方案。 ... [详细]
  • 本文详细介绍了数据库并发控制的基本概念、重要性和具体实现方法。并发控制是确保多个事务在同时操作数据库时保持数据一致性的关键机制。文章涵盖了锁机制、多版本并发控制(MVCC)、乐观并发控制和悲观并发控制等内容。 ... [详细]
  • 阿里巴巴终面技术挑战:如何利用 UDP 实现 TCP 功能?
    在阿里巴巴的技术面试中,技术总监曾提出一道关于如何利用 UDP 实现 TCP 功能的问题。当时回答得不够理想,因此事后进行了详细总结。通过与总监的进一步交流,了解到这是一道常见的阿里面试题。面试官的主要目的是考察应聘者对 UDP 和 TCP 在原理上的差异的理解,以及如何通过 UDP 实现类似 TCP 的可靠传输机制。 ... [详细]
  • OpenAI首席执行官Sam Altman展望:人工智能的未来发展方向与挑战
    OpenAI首席执行官Sam Altman展望:人工智能的未来发展方向与挑战 ... [详细]
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
  • 无论是在迁移到云服务还是更换云服务商的过程中,数据迁移都是一个至关重要的环节。本文将探讨数据迁移中可能遇到的问题及解决方案,包括路径问题、速度问题和数据完整性等。 ... [详细]
  • Manacher算法详解:寻找最长回文子串
    本文将详细介绍Manacher算法,该算法用于高效地找到字符串中的最长回文子串。通过在字符间插入特殊符号,Manacher算法能够同时处理奇数和偶数长度的回文子串问题。 ... [详细]
  • 本文探讨了基于协同过滤算法的个性化新闻推荐系统中,新闻与新闻之间的相似度是如何计算和存储的,并进一步分析了类似系统的实际应用。 ... [详细]
  • 深入理解二分查找及其应用
    二分查找是一种高效的搜索算法,适用于有序数据集合。其核心思想是通过不断将查找区间缩小一半,直至找到目标元素或区间为空。本文将详细介绍二分查找的基本原理、实现方法以及应用场景的局限性。 ... [详细]
  • 如何修改360极速浏览器的默认安装路径
    本文介绍了一种有效的方法,帮助用户在新版360极速浏览器中成功更改默认安装路径,解决因权限问题导致的安装失败。 ... [详细]
  • 2020年9月15日,Oracle正式发布了最新的JDK 15版本。本次更新带来了许多新特性,包括隐藏类、EdDSA签名算法、模式匹配、记录类、封闭类和文本块等。 ... [详细]
  • 本文详细探讨了几种常用的Java后端开发框架组合及其具体应用场景。通过对比分析Spring Boot、MyBatis、Hibernate等框架的特点和优势,结合实际项目需求,为开发者提供了选择合适框架组合的参考依据。同时,文章还介绍了这些框架在微服务架构中的应用,帮助读者更好地理解和运用这些技术。 ... [详细]
  • 本文详细解析了 Yii2 框架中视图和布局的各种函数,并综述了它们在实际开发中的应用场景。通过深入探讨每个函数的功能和用法,为开发者提供了全面的参考,帮助他们在项目中更高效地利用这些工具。 ... [详细]
  • 深入解析 SAP UI5 Page 控件的构造函数参数及其应用
    深入解析 SAP UI5 Page 控件的构造函数参数及其应用 ... [详细]
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社区 版权所有