priority_queue的使用与模拟实现

news2024/9/20 20:37:12

目录

priority_queue的使用

priority_queue的介绍

priority_queue的定义方式

priority_queue成员函数的介绍

priority_queue的模拟实现

1:堆的向上调整算法

2:堆的向下调整算法

两种算法的比较与各自最佳使用 

priority_queue的模拟实现


priority_queue的使用

priority_queue的介绍

priority_queue是C++ STL中的一种容器适配器,它提供了一种优先级队列的实现。优先级队列是一种特殊的队列,具有自动排序的功能,使得队列中的元素始终按照一定的优先级顺序排列,通常是由比较函数或者元素自身的比较操作符来定义。

priority_queue中的元素按照优先级进行排序,最高优先级的元素永远位于队列的顶部,可以方便地获取到具有最高优先级的元素。

在priority_queue中,可以使用push操作添加元素,pop操作移除顶部元素,top操作获取顶部元素(即具有最高优先级的元素)等。

priority_queue的底层实现通常采用堆(heap)数据结构,一般情况下是最大堆(元素值大的在顶部)或最小堆(元素值小的在顶部)。(也就是说默认为大堆存贮)

总的来说,priority_queue提供了一种方便高效的优先级队列实现,对于需要按照优先级排列元素的情况下很有用。

priority_queue的定义方式

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

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

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

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

方式三: 不指定底层容器和内部需要构造的堆结构。

priority_queue<int> q;

注意: 此时默认使用vector作为底层容器,内部默认构造大堆结构

priority_queue成员函数的介绍

成员函数功能
push()插入元素到队尾(并排序)
pop()弹出队头元素(堆顶元素)
top()访问队头元素(堆顶元素)
size()获取队列中有效元素个数
empty()判断队列是否为空
swap()交换两个队列的内容

使用案列举例:

#include <iostream>
#include <queue>
#include<vector>
using namespace std;
int main()
{
	priority_queue<int> q;
	q.push(3);
	q.push(6);
	q.push(0);
	q.push(2);
	q.push(9);
	q.push(8);
	q.push(1);
	q.push(10);
	while (!q.empty())
	{
		cout << q.top() << " ";
		q.pop();
	}
	cout << endl;
	return 0;
}



打印结果:
//10 9 8 6 3 2 1 0

priority_queue的模拟实现

 上面也介绍了,优先接队列的底层实现通常采用堆(heap)数据结构,在默认大堆的情景下,我们在这里温习一下堆的几个关键性操作。

1:堆的向上调整算法

假如我们已经建立了这样的一个大堆, 如果在push7,那么就会在5的右子树先插入7,变为如图所示;

然后根据向上调整,由大堆的优先级比较,会与5进行交换 

然后再次与6根据大堆的优先级比较后得知还需要与6进行交换 

同理得知,就不需要再次9进行交换调整堆了。这就是向上调整。 

2:堆的向下调整算法

就比如这样一个堆,我们要进行向下调整的算法,那么他就有一个前提,那么就是图中用蓝色框起来的左子树与右子树要保证是大堆。

 向下调整其中有一个要注意的细节点,就是假如堆的顶部是5,5<6也5<8,5既可以与8交换也可以与6交换,但是如果与6交换后此时的顶是6但是6<8,还需要进行交换,所以向下调整算法有一个注意点就是:向下调整要与他的两个子结点中最大的哪一个进行交换。

当然这种特殊情况,对于图中给出的案例是不涉及的,不需要进行考虑。

只需要将7与8进行交换就完整了整个调整的过程 

两种算法的比较与各自最佳使用 

对于一个已经是大堆的情况下:

设节点总数为 n,则树的高度为 log⁡n。由此可知,堆化操作的循环轮数最多为 log⁡n次 ,所以两种调整的算法,最差的时间复杂度就为0(logn);所以在此情况下,两种堆的调整算法以时间复杂度来说是大差不差的。

但是你肯定听过一句这样的话:向下调整的效率>>向上调整,那么这句话是从何而来呢?

这其实是涉及到给你一个已知的一个乱序数组,然后分别利用两种算法来进行调整,在这种情景下来说:向下调整的效率>>向上调整。

我也找到了对应的别人的推导算法:

本图找自:堆的向下调整算法、堆的向上调整算法、堆的基本功能实现_堆的调整-CSDN博客

向上调整的没有找到,那么就由我来补充推到:

因为2^{h}(h-2)+2=(N+1)[log(N+1)-2]

用大O的渐进表示法:
T ( n ) = NlogN>>N

所以这也就是为什么会有向下调整的效率远远大于向上调整。

两种调整的匹配使用情况:

向下调整可以运用到用数组初始化堆,向上调整可以运用到入堆,对于删除堆顶的操作,是先将堆顶与堆低进行交换后,删除堆底后,在对顶用进行向下调整;

 说到这里了,那么这里就给出两种调整的算法实现把:

void adjustment_prev(Hp* php,int child)//升的排序   大堆
{
	assert("php");
	assert(!HeapEmpty(php));
	int parent = (child - 1) / 2;
	while (parent>=0)
	{
		if (php->a[child] > php->a[parent])//调换
		{
			swap(&php->a[child], &php->a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			//不交换
			break;
		}
	}
}
void adjustment_down(HpDataType* a,int n,int parent )
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if ((child + 1 < n) && (a[child] > a[child + 1]))
		{
			child++;
		}
		if (a[child] > a[parent])
		{
			swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

priority_queue的模拟实现

成员函数实现方法
push()在容器尾部插入元素后进行一次向上调整算法
pop()将容器头部和尾部元素交换,再将尾部元素删除,最后从根结点开始进行一次向下调整算法
top()返回容器的第0个元素
size()返回容器的当前大小
empty()判断容器是否为空

template<class T, class Container = vector<T>, class Compare = Less<T>>
class priority
{
public:
	priority()
	{}
	template <class InputIterator>
	priority(InputIterator first, InputIterator last)
		:_con(first, last)
	{
		for (int i = (_con.size() - 2) / 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 push(const T& x)
	{
		_con.push_back(x);
		adjust_up(_con.size() - 1);
	}
	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] < _con[child + 1])
			if (child + 1 < _con.size()
				&& _con[child] < _con[child + 1])
			{
				++child;
			}
			if (com(_con[parent], _con[child]))
			{
				swap(_con[parent], _con[child]);
				parent = child;
				child = parent * 2 + 1;
			} 
			else
			{
				break;
			}
		}
	}
	void pop()
	{
		swap(_con[0], _con[_con.size() - 1]);
		_con.pop_back();
		adjust_down(0);
	}		
	const T& top()
	{
		return _con[0];
	}
	bool empty()
	{
		return _con.empty();
	}
	size_t size()
	{
		return _con.size();
	}
private:
	Container _con;
};	

需要解释的一点就是整个库函数,其实跟qsort差不多,但是整个是对应的建立大堆时使用的函数,他的作用就是比较两个数 

就比如上图中的这个使用情况,如果操作数一<操作数二,那么就返回真。

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

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

相关文章

使用VMware虚拟机安装kali 2019

一、下载kali linux镜像 下载 kali Linux的ISO镜像文件 网盘链接&#xff1a;https://pan.baidu.com/s/1GRtJxGBlqFfmU24HLEy3-g?pwd57u3 提取码&#xff1a;57u3 二、安装并配置 Kali Linux 新建虚拟机 在虚拟机创建向导中&#xff0c;选择经典配置 选择下载好的kali镜…

细说MCU用定时器控制ADC采样频率的实现方法并通过Simulink查看串口输出波形

目录 一、硬件工程 二、建立Simulink模型 1.安装MATLAB和Simulink 2.建立Simulink模型 三、代码修改 1.修改回调函数 2.产看结果 3.完整的main.c 本文作者的文章 细说MCU用定时器控制ADC采样频率的实现方法-CSDN博客 https://wenchm.blog.csdn.net/article/details/…

WSL-Ubuntu20.04环境使用YOLOv8 TensorRT推理加速

在阅读本章内容之前,需要把部署环境以及训练环境都安装好。 1.TensorRTX下载 这里使用Wang-xinyu大佬维护的TensorRTX库来对YOLOv8进行推理加速的演示,顺便也验证一下前面环境配置的成果。 github地址:GitHub - wang-xinyu/tensorrtx,下载后放到wsl的路径下,我这里放在/h…

JavaScript日期对象倒计时案例

思路&#xff1a;1.先求出当前时间的总毫秒数 2.再求出所需要求的时间的总毫秒数 3.用所求时间的减去当前时间的可得到倒计时剩余时间 4.最后将所求的倒计时剩余时间转换为天&#xff0c;小时&#xff0c;分钟&#xff0c;秒即可 <!DOCTYPE html> <html lang"en…

Java并发04之线程同步机制

文章目录 1 线程安全1.1 线程安全的变量1.2 Spring Bean1.3 如果保证线程安全 2 synchronized关键字2.1 Java对象头2.1.1 对象组成部分2.1.2 锁类型2.1.3 锁对象 2.2 synchronized底层实现2.2.1 无锁状态2.2.2 偏向锁状态2.2.3 轻量级锁状态2.2.4 重量级锁2.2.5 锁类型总结2.2.…

【动态规划】力扣2266.统计打字方案数

Alice 在给 Bob 用手机打字。数字到字母的 对应 如下图所示。在这里插入图片描述 为了 打出 一个字母&#xff0c;Alice 需要 按 对应字母 i 次&#xff0c;i 是该字母在这个按键上所处的位置。 比方说&#xff0c;为了按出字母 ‘s’ &#xff0c;Alice 需要按 ‘7’ 四次。…

C++:类的默认成员函数

默认成员函数就是⽤⼾没有显式实现&#xff0c;编译器会⾃动⽣成的成员函数称为默认成员函数。⼀个类&#xff0c;我们不写的情况下编译器会默认⽣成以下6个默认成员函数&#xff0c;需要注意的是这6个中最重要的是前4个。 定义一个空类&#xff1a; class A { }; 经过编译器…

Etsy开店指南:分步指南与防封技巧

您的Etsy帐户在注册后不久就被封了吗&#xff1f;如果是这样&#xff0c;您在设置Etsy帐户时就已经错误了&#xff0c;其实这其中还是有很多细节需要注意&#xff1b;本文全面讲解了如何逐步创建帐户&#xff0c;如果你也正在准备&#xff0c;那就继续看吧&#xff01; 一、在开…

基于Java的汽车租赁管理系统设计(含文档、源码)

本篇文章论述的是基于Java的汽车租赁管理系统设计的详情介绍&#xff0c;如果对您有帮助的话&#xff0c;还请关注一下哦&#xff0c;如果有资源方面的需要可以联系我。 目录 摘 要 系统运行截图 系统总体设计 系统论文 资源下载 摘 要 近年来&#xff0c;随着改革开放…

元宇宙:科技巨头的下一个战场

热门标题&#xff1a; “元宇宙&#xff1a;科技巨头的下一个战场” 相关文章问题&#xff1a; 问题&#xff1a; 在科技巨头纷纷布局元宇宙的背景下&#xff0c;元宇宙将如何影响未来的科技产业和日常生活&#xff1f; 文章概要&#xff1a; 随着Facebook更名为Meta&…

Unity XR Interaction Toolkit的安装(二)

提示&#xff1a;文章有错误的地方&#xff0c;还望诸位大神不吝指教&#xff01; 文章目录 前言一、安装1.打开unity项目2.打开包管理器&#xff08;PackageManage&#xff09;3.导入Input System依赖包4.Interaction Layers unity设置总结 前言 安装前请注意&#xff1a;需要…

吴恩达深度学习笔记:机器学习策略(2)(ML Strategy (2)) 2.9-2.10

目录 第三门课 结构化机器学习项目&#xff08;Structuring Machine Learning Projects&#xff09;第二周&#xff1a;机器学习策略&#xff08;2&#xff09;(ML Strategy (2))2.9 什么是端到端的深度学习&#xff1f;&#xff08;What is end-to-end deep learning?&#x…

前端转base64格式的字体图标方法

1.将需要的字体图标包下载到本地 2.访问 transfonter.org 将字体图标转成base64格式 如 这样就可以和正常的字体图标一样使用了

【深度学习驱动智能超材料设计与应用】

在深度学习与超材料融合的背景下&#xff0c;不仅提高了设计的效率和质量&#xff0c;还为实现定制化和精准化的治疗提供了可能&#xff0c;展现了在材料科学领域的巨大潜力。深度学习可以帮助实现超材料结构参数的优化、电磁响应的预测、拓扑结构的自动设计、相位的预测及结构…

【HTML入门】第十五课 - form表单(下)表单控件们(二)

上一小节我们说了文本输入框&#xff0c;密码输入框&#xff0c;数值型输入框&#xff0c;还有大的文本域。这一小节&#xff0c;我们继续说form表单中的一些常用的控件们。 目录 1 单选按钮 2 复选框 3 下拉列表选择 1 单选按钮 单选按钮&#xff0c;就是说一组按钮中&am…

栈(用C语言实现)

1. 栈 1.1 概念与结构 栈&#xff1a;⼀种特殊的线性表&#xff0c;其只允许在固定的⼀端进行插入和删除元素操作。进行数据插入和删除操作的⼀端称为栈顶&#xff0c;另⼀端称为栈底。栈中的数据元素遵守后进先出 LIFO&#xff08;Last In First Out&#xff09;的原则。 压…

多源字段聚合重塑算法

要求如下 [[{"oone": "评估是否聘请第三方机构","otwo": null,"othree": "test",},{"oone": "评估是否聘请第三方机构","otwo": null,"othree": "test",}],[{"oon…

使用 Flask 3 搭建问答平台(三):注册页面模板渲染

前言 前端文件下载 链接https://pan.baidu.com/s/1Ju5hhhhy5pcUMM7VS3S5YA?pwd6666%C2%A0 知识点 1. 在路由中渲染前端页面 2. 使用 JinJa 2 模板实现前端代码复用 一、auth.py from flask import render_templatebp.route(/register, methods[GET]) def register():re…

Elasticsearch:评估搜索相关性 - 第 1 部分

作者&#xff1a;来自 Elastic Thanos Papaoikonomou, Thomas Veasey 这是一系列博客文章中的第一篇&#xff0c;讨论如何在更好地理解 BEIR 基准的背景下考虑评估你自己的搜索系统。我们将介绍具体的技巧和技术&#xff0c;以便在更好地理解 BEIR 的背景下改进你的搜索评估流程…

java用freemarker导出word

freemarker导出word 第一步、将word转换为xml格式第二步、将转换后的xml文件修改后缀为ftl后复制到项目 resources 目录下&#xff08;可以自己新建一个文件夹放在文件夹中&#xff09;第三步、格式化xml代码&#xff08;如果问价太大可能会无法格式化&#xff09;这时候需要在…