【priority_queue的模拟实现】

news2025/1/14 18:44:07

priority_queue的模拟实现

小杨

容器适配器:priority_queue

priority_queue即优先级队列是一种容器适配器,根据严格的弱排序标准(即排序规则可以更改),他的第一个元素总是它所包含的元素中最大的。优先队列将特定容器类封装作为其底层容器类。标准容器类vector和deque满足这些需求。默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用vector。

对于优先队列来说,需要支持随机访问迭代器,以便始终在内部保持堆结构。

优先级队列的接口

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

函数声明接口说明
priority_queue()构造一个空的优先级队列
priority_queue(first,last)从给定的迭代器范围[first,last]中构建优先级队列,并调用调整方法,确保优先队列内部的元素始终保持堆结构
empty()检测优先级队列是否为空,是返回true,否则返回false
top()返回优先级队列中最大(最小元素),即堆顶元素
push(x)在优先级队列中插入元素x
pop()删除优先级队列中最大(最小)元素,即堆顶元素

优先级队列涉及到堆的核心

为什么现有的元素是堆,插入元素了还能保持堆,即使删除了元素也能保持堆的性质,那么这个是因为向上调整算法和向下调整算法存在的原因。

向下调整算法

在用给定迭代器区间构造中,我们要用到向下调整算法,从而来实现保持他为堆的结构,并且删除元素时,即调用pop时,需要交换堆顶和堆尾的元素,然后删除堆尾,然后这个时候也是要用到向下调整算法的。
但是要用向下调整算法是要有条件的,以大堆为例子,就是你要向下调整的那个节点的左右子树必须必须都是大堆。
知道了这一点,来解释一下为什么上述两个条件都能默认用向下调整算法嘞,首先我们在使用迭代器区间构造时,肯定不能直接用向下调整算法,因为根节点左右子树可能不是堆,因此我们采用的是从倒数的第一个非叶子节点的子树开始调整,为什么嘞,因为此时倒数的第一个非叶子节点的左右子树的都分别只有一个叶子节点,这个时候,是大堆是小堆都可以,因此从倒数的第一个非叶子结点开始向上调整,一直调整到根节点的树,就可以调整成堆。而删除呢?先交换堆顶和堆尾,然后删除堆尾的元素,这个时候必定要向下调整了,因为我们的堆默认是大堆,这个时候把最小的数放到堆顶了,破坏了堆的结构,并且此时堆顶的左右子树都是大堆,因此就可以调整了。
请添加图片描述
向下调整代码:

void AdjustDown(int parent)
{
	int child = parent * 2 + 1;


	while (child < c.size())
	{
		if (child + 1 < c.size() && comp(c[child], c[child + 1]))
		{
			child++;
		}


		if (comp(c[parent], c[child]))
		{
			swap(c[parent], c[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			return;
		}
	}
}
向上调整算法

以大堆为例子,堆的向上调整算法在插入新元素的时候会用到,这个时候他的插入元素的父母是唯一确定的。然后如果插入的这个值比父亲节点大,就进行交换,庵后按照这个规律向上继续调整,停止条件是如果当孩子节点为堆顶时停止或者该节点比父亲节点小。

以下图为例子,本来是一个大堆,我又插入了一个70,破坏了大堆的结构,然后因此需要进行向上调整算法。70比其父节点30大,因此需要交换
在这里插入图片描述

在这里插入图片描述
交换完毕后,70的父节点75,满足大堆结构,因此此时停止调整就好。
堆向上调整代码:

	void AdjustUp(int child)
	{
		int parent = (child - 2) / 2;
		while (child > 0)
		{
			if (comp(c[parent], c[child]))
			{
				swap(c[parent], c[child]);
				child = parent;
				parent = (child - 2) / 2;
			}
			else
			{
				break;
			}
		}
	}

priority_queue模拟实现代码

namespace yang
{

	template<class T>
	struct less
	{
		bool operator()(const T& left, const T& right)
		{
			return left < right;
		}
	};


	template<class T>
	struct greater
	{
		bool operator()(const T& left, const T& right)
		{
			return left > right;
		}


	};
	template <class T, class Container = std::vector<T>, class Compare = less<T> >
	class priority_queue
	{
	public:
		priority_queue()
			:c()
			, comp()
		{


		}
		template <class InputIterator>
		priority_queue(InputIterator first, InputIterator last)
			: c()
			, comp()
		{
			int count = c.size();
			int root = (count - 2) / 2;
			for (int i = root; i >= 0; --i)
			{
				AdjustDown(i);
			}
		}
		bool empty() const
		{
			return c.empty();
		}
		size_t size() const
		{
			return c.size();
		}
		const T& top() const
		{
			return c.front();
		}
		void push(const T& x)
		{
			c.push_back(x);
			AdjustUp(c.size() - 1);
		}
		void pop()
		{
			if (c.empty())
				return;


			swap(c.front(), c.back());
			c.pop_back();
			AdjustDown(0);
		}
	private:
		void AdjustUp(int child)
		{
			int parent = (child - 2) / 2;
			while (child > 0)
			{
				if (comp(c[parent], c[child]))
				{
					swap(c[parent], c[child]);
					child = parent;
					parent = (child - 2) / 2;
				}
				else
				{
					break;
				}
			}
		}


		void AdjustDown(int parent)
		{
			int child = parent * 2 + 1;


			while (child < c.size())
			{
				if (child + 1 < c.size() && comp(c[child], c[child + 1]))
				{
					child++;
				}


				if (comp(c[parent], c[child]))
				{
					swap(c[parent], c[child]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					return;
				}
			}
		}
		Container c;
		Compare comp;
	};
};

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

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

相关文章

ElasticSearch优化实战:打造高性能搜索引擎的秘籍

在当今这个大数据时代&#xff0c;信息的海量增长对搜索技术提出了前所未有的挑战。用户不仅需要快速准确地从数以亿计的数据中找到所需信息&#xff0c;还希望搜索引擎能够提供个性化和智能化的搜索体验。ElasticSearch作为市场上领先的搜索引擎&#xff0c;因其强大的全文搜索…

Typora2024最新版破解方法(亲测可用)

此方法非常简单&#xff0c;无需安装dll补丁&#xff0c;无需修改注册表&#xff0c;无需使用老版本。仅需修改部分文件内容即可 方法步骤 步骤一 下载并安装Typora 安装Typora 打开官网 下载并安装最新版即可 点击访问Typora官网 https://typoraio.cn/ 步骤二 修改文件 …

java面向对象重点总结

文章目录 java面向对象重点总结类与实例构造方法方法重载属性与修饰符封装继承多态重构抽象类接口抽象类和接口的区别&#xff1a;集合泛型 java面向对象重点总结 对象是一个自包含的实体&#xff0c;用一组可识别的特性和行为来标识。 面向对象编程&#xff0c;英文叫Object…

mcasttest-tool组播检测工具

作者&#xff1a;广大 检测组播 mcasttest-tool是oracle组播检测工具&#xff0c;组播是oracle 11.2.0.2开始的新功能。 1、上传mcasttest工具解压并授权 [rootrac1 soft]# cd /u01/soft/ [rootrac1 soft]# tar -xvf mcasttest.tgz[rootrac1 soft]# chown -R grid:oinstall…

Animate软件基础:“分散到图层”创建的新图层

FlashASer&#xff1a;AdobeAnimate2021软件零基础入门教程https://zhuanlan.zhihu.com/p/633230084 FlashASer&#xff1a;实用的各种Adobe Animate软件教程https://zhuanlan.zhihu.com/p/675680471 FlashASer&#xff1a;Animate教程及作品源文件https://zhuanlan.zhihu.co…

Pytorch实现线性回归Linear Regression

借助 PyTorch 实现深度神经网络 - 线性回归 - 第 2 周 | Coursera 线性回归预测 用PyTorch实现线性回归模块 创建自定义模块&#xff08;内含一个线性回归&#xff09; 训练线性回归模型 对于线性回归&#xff0c;特定类型的噪声是高斯噪声 平均损失均方误差函数&#xff1a…

Mallet:一款针对任意协议的安全拦截代理工具

关于Mallet Mallet是一款功能强大的协议安全分析工具&#xff0c;该工具支持针对任意协议创建用于安全审计的拦截代理&#xff0c;该工具本质上与我们所熟悉的拦截Web代理类似&#xff0c;只是通用性更强。 工具运行机制 Mallet建立在Netty框架之上&#xff0c;并且依赖于Net…

文案人的梦工场,网易入职指南!

网易云对于咱们一些有点文艺的文案策划来说&#xff0c;简直就是梦中情司。 在这里工作锻炼机会很多&#xff0c;也很开拓眼界&#xff0c;能获得相当于在别处3倍能力的成长速度&#xff0c;福利待遇也是很好的。 要进入网易云音乐做文案策划&#xff0c;你可以按照以下步骤进…

数据结构的基本概念与算法2

线性表 &#xff1a; 线性表 是具有相同数据类型的 n (n > 0) 个数据元素的有限序列&#xff0c;其中 n 为表长&#xff0c;当 n 0 时线性表是一个空表&#xff1b;若用 L 命名线性表&#xff0c;则其一般表示为&#xff1a;L (a1 , a2 , ... ai , ai1 , ... an) 上述中&a…

月木学途开发 2.项目架构

1.项目介绍 月木学途是一款it在线学习网站&#xff0c;项目采用前后端分离架构。前端开发主要使用vue.js&#xff0c;后端使用Spring Cloud Alibaba技术栈。项目包含学习网站的大部分功能&#xff0c;分为管理员端和用户端。管理员端有权限管理、课程管理、网站管理、求职模块管…

Shell函数和Shell 输入/输出重定向

LInux&#xff1a;Shell函数和Shell 输入/输出重定向 Shell函数 参数说明&#xff1a; 可以带function fun() 定义&#xff0c;也可以直接fun() 定义,不带任何参数。参数返回&#xff0c;可以显示加&#xff1a;return 返回&#xff0c;如果不加&#xff0c;将以最后一条命令运…

[Vue warn]: data functions should return an object:

仔细检查你的代码肯定有一个data()内忘记方return{}了

C语言程序设计23

《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 例题2.11 从键盘输入B、O、Y三个字符&#xff0c;然后把他们输出到屏幕上 代码&#xff1a; //《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 //例题2.11 从键盘输入B、O、Y三个字符&#xff0c;然…

RabbitMQ:MQ的可靠性

MQ的可靠性 在默认情况下&#xff0c;RabbitMQ会将接收到的信息保存在内存中以降低消息收发的延迟。这样会导致两个问题: 一旦MQ宕机&#xff0c;内存中的消息会丢失 内存空间有限&#xff0c;当消费者故障或处理过慢时&#xff0c;会导致消息积压&#xff0c;引发MQ阻塞。 …

高效、安全、共享|济南市升级教育城域网,重塑教育网络生态

文/济南市电化教育馆 电教教研室主任 张承强 导语: 近年来,济南市教育局以前瞻性的视野,将教育数字化转型视为推动教育高质量发展的基石,全力加速教育现代化进程。在这一蓝图下,教育城域网的升级改造项目被赋予了基础性、先导性和战略性的重要意义,成为探索教育数字化转型新路…

一键搞定PDF翻译,这四款是职场达人常备翻译工具!!!

作为外贸搬砖人的一份子&#xff0c;虽说外语功底还说地过去&#xff0c;但是每天过目大量pdf文件的翻译&#xff0c;难免还有些吃力&#xff0c;这个时候如果有可以辅助翻译的工具那就再好不过了&#xff0c;今天给大家带来四款非常适合pdf文件翻译的工具&#xff0c;总有一款…

C#中的通信

上位机应用开发-串口通信1、基于C#的串口通信对象:SerialPort 2、字段属性 PortName:获取或设置通信端口 BaudRate:获取或设置串行波特率-DataBits:获取或设置每个字节的标准数据位长度 Parity:获取或设置奇偶校验检查协仪I-StopBits;获取或设置每个字节的标准停止位数 3、…

你需要的Node版本管理神器NVM

在做项目的时候&#xff0c;很多人本地的node都是装一个固定版本&#xff0c;一旦有些项目要下的依赖需要更高版本的node支持的时候&#xff0c;此时需要升级node就得把已经安装的低版本node卸载了&#xff0c;然后再重新下载、安装高版本的node,既费时间又抓狂&#xff0c;特别…

大模型算法面试题(十九)

本系列收纳各种大模型面试题及答案。 1、SFT&#xff08;有监督微调&#xff09;、RM&#xff08;奖励模型&#xff09;、PPO&#xff08;强化学习&#xff09;的数据集格式&#xff1f; SFT&#xff08;有监督微调&#xff09;、RM&#xff08;奖励模型&#xff09;、PPO&…

网工内推 | 云运维工程师,最高19K,五险一金加补充医疗险

01 云计算运维工程师 &#x1f537;岗位职责 1、负责客户云计算解决方案的运维&#xff0c;负责云计算解决方案中云、虚拟化工作&#xff1b; 2、负责客户现场H3C产品的日常问题处理、变更维护、巡检、版本升级等工作&#xff0c;保障客户网络的稳定运行&#xff1b; 3、协调…