C++ —— 优先级队列(priority queue)的模拟实现

news2024/11/20 6:23:41

目录

杂谈

vector和list的区别

1. 优先级队列的定义

2. 优先级队列的模拟实现

3. 仿函数


链接:

priority_queue - C++ Reference (cplusplus.com)icon-default.png?t=O83Ahttps://legacy.cplusplus.com/reference/queue/priority_queue/?kw=priority_queue


杂谈

vector和list的区别

在这种情况下诞生了一个缝合怪:deque

 

但是依旧有缺陷 


1. 优先级队列的定义

队列是一种先进先出的数据类型。元素的入队都只能从队尾进入,出队时从队列头部出去

*

优先级队列不能先进先出,更像是数据类型中的“”,也就是数组

优先级队列每次出队的元素是队列中优先级最高的那个元素,默认大的值优先级高,如果想要小的值优先级高可以使用仿函数,而不是队首的元素,也就是每次出队,都是将当前队列中最大的那个元素出队


2. 优先级队列的模拟实现

假设父节点在数组中的下标为i,那么:

                                                        1.左孩子在数组中的下标为:2*i+1 

                                                        2.右孩子在数组中的下标为:2*i+2

假设孩子在数组中的下标为i,那么:

                                                        父在数组中的下标为:(i - 1)/ 2

在这里不区分左孩子和右孩子,因为除以会向下取整

#pragma once
//优先级队列:默认大的值优先级高,如果想要小的值优先级高可以使用仿函数
//底层是堆
namespace bit
{
	template<class T, class Container = vector<T>>
	class priority_queue
	{
	public:
		//堆的向上调整
		void AdjustUp(size_t child)
		{
			//孩子/2找到父节点
			int parent = (child - 1) / 2;
			//孩子大于0就进入/继续
			while (child > 0)
			{
				//如果孩子小于父亲
				if (_con[parent] < _con[child])
				{
					swap(_con[parent], _con[child]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

		//向下调整
		void AdjustDown(size_t parent)
		{
			// 先假设左孩子小
			int child = parent * 2 + 1;

			// child >= n说明孩子不存在,调整到叶子了
			while (child < 0)
			{
				//找到大的子结点 
				if (child + 1 < _con.size() && _con[child] < _con[child + 1])
				{
					child++;
				}
				//if (_con[child] > _con[parent]) 大堆
				//孩子小于父亲
				if (_con[child] < _con[parent])//小堆
				{
					swap(_con[child], _con[parent]);
					parent = child;
					//继续算左孩子
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}



			void push(const T & x)
			{
				//插入数据之前已经是一个堆了,那么数据就要
				_con.push_back(x);

				//从堆底向上调整
				AdjustUp(_con.size() - 1);
			}

			void pop()
			{
				swap(_con[0], _con[_con.size() - 1]);
				_con.pop_back();
				AdjustDown(0);
			}

			const T& top()
			{
				return _con[0];
			}

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

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

		private:
			Container _con;
		};
	}


3. 仿函数

仿函数的本质是一个类,使用到了仿函数来重载 operator(),以达到改变大/小堆的功能,他的对象可以像函数一样使用

// 仿函数:本质是一个类,这个类重载operator(),他的对象可以像函数一样使用
template<class T>
class Less
{
public:
	bool operator()(const T& x, const T& y)
	{
		return x < y;
	}
};

template<class T>
class Greater
{
public:
	bool operator()(const T& x, const T& y)
	{
		return x > y;
	}
};
#pragma once
//优先级队列:默认大的值优先级高,如果想要小的值优先级高可以使用仿函数
//底层是堆
namespace bit
{
	template<class T, class Container = vector<T>>
	class priority_queue
	{
	public:
		//堆的向上调整
		void AdjustUp(size_t child)
		{
			Compare com;
			//孩子/2找到父节点
			int parent = (child - 1) / 2;
			//孩子大于0就进入/继续
			while (child > 0)
			{
				//如果孩子小于父亲
				//if (_con[parent] < _con[child])
				//将大的值移向堆顶,建大堆
				if (com(_con[child], _con[parent]))
				{
					swap(_con[parent], _con[child]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

		//向下调整
		void AdjustDown(size_t parent)
		{
			Compare com;
			// 先假设左孩子小
			int child = parent * 2 + 1;

			// child >= n说明孩子不存在,调整到叶子了
			while (child < 0)
			{
				//找到大的子结点 
				//if (child + 1 < _con.size() && _con[child] < _con[child + 1])
				if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
				{
					child++;
				}
				//if (_con[child] > _con[parent]) 大堆
				//孩子小于父亲
				//if (_con[child] < _con[parent])//小堆
				if (com(_con[parent], _con[child]))
				{
					swap(_con[child], _con[parent]);
					parent = child;
					//继续算左孩子
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}



			void push(const T & x)
			{
				//插入数据之前已经是一个堆了,那么数据就要
				_con.push_back(x);

				//从堆底向上调整
				AdjustUp(_con.size() - 1);
			}

			void pop()
			{
				swap(_con[0], _con[_con.size() - 1]);
				_con.pop_back();
				AdjustDown(0);
			}

			const T& top()
			{
				return _con[0];
			}

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

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

		private:
			Container _con;
		};
	}

感谢观看~

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

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

相关文章

Elastic Stack--16--ES三种分页策略

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 方式一&#xff1a;from size实现原理使用方式优缺点 方式二&#xff1a;scroll实现原理使用方式优缺点 方式三&#xff1a;search_after实现原理使用方式优缺点 三…

两个pdf怎么合并成一个pdf?超简单的合并方法分享

在日常工作和学习中&#xff0c;我们经常会遇到需要将多个PDF文件合并成一个文件的情况&#xff0c;以便更好地管理和分享。今天&#xff0c;将为大家详细介绍5种实用的方法&#xff0c;能够一键合并多个PDF文件&#xff0c;有需要的小伙伴快来一起学习下吧。 方法一&#xff1…

双十一买什么?双十一买什么东西最划算?超全双十一购物指南!

双十一即将到来&#xff0c;一年一度的购物狂欢盛宴再度开启&#xff01;在海量的商品面前&#xff0c;怎样挑选出既心仪又实惠的好物&#xff0c;已然成为大家关注的重点。下面为您呈上一份极为全面的2024年双十一必买清单&#xff0c;助力您轻松购物&#xff0c;收获满满&…

详解Xilinx JESD204B PHY层端口信号含义及动态切换线速率(JESD204B五)

Xilinx官方提供了两个用于开发JESD204B的IP&#xff0c;其中一个完成PHY层设计&#xff0c;另一个完成传输层的逻辑&#xff0c;两个IP必须一起使用才能正常工作。 7系列FPGA只能使用最多12通道的JESD204B协议&#xff0c;线速率为1.0至12.5 Gb/s&#xff1b;而UltraScale和Ult…

胤娲科技:AI评估新纪元——LightEval引领透明化与定制化浪潮

AI评估的迷雾&#xff0c;LightEval能否拨云见日&#xff1f; 想象一下&#xff0c;你是一位AI模型的开发者&#xff0c;精心打造了一个智能助手&#xff0c;却在最终评估阶段遭遇了意外的“滑铁卢”。 问题出在哪里&#xff1f;是模型本身不够聪明&#xff0c;还是评估标准太过…

新手如何打造抖音矩阵账号,矩阵账号的优势有哪些?如何搭建矩阵系统的源码开发oem部署

抖音新手如何打造爆款矩阵账号&#xff1f; 在当前数字媒体盛行的时代&#xff0c;抖音作为一个领先的短视频分享平台&#xff0c;为品牌和个人提供了展示自己的舞台。对于初学者而言&#xff0c;构建一个有效的抖音账号矩阵是提升影响力的关键策略&#xff01;今天&#xff0c…

mysql内置函数查询

聚合函数 &#xff1a;聚合函数查询时纵向查询&#xff0c;它是对一列的 值进行计算&#xff0c;然后返回一个单一的值&#xff0c;聚合函数会忽略空值。 namedescriptionavg()返回参数的平均值bit_and()按位返回andbit_or()按位返回orbit_xor()按位返回异或count()返回返回的…

Uos-Uos使用Remmina通过VNC远程连接到另一台Uos

Uos使用Remmina通过VNC远程连接到另一台Uos 一、概述二、对端机器安装 VNC服务器三、本机远程对端服务器 一、概述 这里记录一下使用Remmina通过VNC远程连接到另一台Uos系统&#xff0c;环境均是Linux操作系统 本机ip&#xff1a;10.8.11.64 对端ip&#xff1a;10.20.42.17 …

进程的状态的理解(概念+Linux)

文章目录 进程的状态并行和并发物理和逻辑 时间片进程具有独立性等待的本质运行阻塞标记挂起等待 Linux下的进程状态&#xff08;一&#xff09;运行状态&#xff08;R - running&#xff09;&#xff08;二&#xff09;睡眠状态&#xff08;S - sleeping&#xff09;&#xff…

银河麒麟V10中启用SELinux

银河麒麟V10中启用SELinux 1、启用SELinux1.1 切换到strict模式1.2 注意 2、验证SELinux状态 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在银河麒麟高级服务器操作系统V10中&#xff0c;可以使用security-switch工具来启用SELinux&…

springboot邮件群发功能的开发与优化策略?

springboot邮件配置指南&#xff1f;如何实现spring邮件功能&#xff1f; SpringBoot框架因其简洁、高效的特点&#xff0c;成为了开发邮件群发功能的理想选择。AokSend将深入探讨SpringBoot邮件群发功能的开发过程&#xff0c;并提出一系列优化策略&#xff0c;以确保邮件发送…

香山南湖架构分析--FE

总体架构 分支预测和指令缓存&#xff0c;通过FTQ达到解耦的目的&#xff1b;FTQ将请求送给ICache,进行取指&#xff1b;取出的指令码通过预译码初步检查分支预测的错误并及时冲刷预测流水线&#xff1b;检查后的指令送入指令缓冲并传给译码模块&#xff0c;最终形成后端的指令…

抓住最后机会!24年PMP认证报名今日开始,流程详解助你成功

为减少同一时间集中报名造成的网络拥堵&#xff0c;本次报名将采取以下形式分地区、分批次开放报名。 一、考试安排 考试时间&#xff1a;2024年11月30日 第一批报名城市 2024年10月9日10&#xff1a;00至10月16日16&#xff1a;00&#xff0c;以下城市的考点将开通报名&…

城市交通场景分割系统源码&数据集分享

城市交通场景分割系统源码&#xff06;数据集分享 [yolov8-seg-C2f-Faster&#xff06;yolov8-seg-GhostHGNetV2等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challenge 项目来源AAAI Glob…

FineReport打开报错“配置数据库出错“怎么解决?

配置数据库被锁住&#xff0c;是否重置?将在embed文件夹生成备份并重置 我直接用管理员身份证打开就完美解决了!

fmql之Linux下AXI GPIO、MISC

AXI GPIO 正点原子第41章。 要使用AXI GPIO&#xff0c;就要在vivado工程中&#xff0c;添加相关的IP。 然后dts会自动生成相关的AXi GPIO的设备树内容。 MISC 正点原子第42章。 /***************************************************************Copyright © ALIENTE…

C++--特殊类的设计

下面所实现类的源码&#xff1a;源码链接 不可拷贝类 在C中&#xff0c;我们有时候需要设计一些不可拷贝的类&#xff0c;即不允许用户通过拷贝构造函数或赋值操作来创建该类的副本。这样设计通常是为了确保资源&#xff08;如文件描述符、窗口句柄等&#xff09;的唯一性&…

(JAVA)熟悉队列的进阶结构 - 优先队列

1. 优先队列 ​ 普通队列是一种先进先出的数据结构&#xff0c;元素在队列尾追加&#xff0c;而从队列头删除。 ​ 在某些情况下&#xff0c;我们可能需要找出队列中的最大值或者最小值&#xff0c;例如使用一个队列保存计算机的任务&#xff0c;一般情况下计算机的任务都是有…

FTP连接池与多线程上传下载算法实现(C语言)

FTP连接池与多线程上传下载算法实现(C语言) 设计思路伪代码示例C代码示例为了避免多线程环境下FTP连接池在故障重连时导致的竞争条件和core dump问题,我们需要设计一个精细的连接池管理系统,确保在连接重连时,其他线程不会尝试使用该连接。以下是一个简化的设计思路和示例…

开源计算器应用的全面测试计划:确保功能性和可靠性

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…