C++STL— priority_queue的使用与模拟实现

news2024/12/24 20:55:08

priority_queue的使用

priority_queue的介绍

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

注意: 默认情况下priority_queue是大堆。

priority_queue的定义方式

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

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

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

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

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

priority_queue<int> q;

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

priority_queue各个接口的使用

priority_queue的各个成员函数及其功能如下:

示例:

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

priority_queue的模拟实现

priority_queue的底层实际上就是堆结构,实现priority_queue之前,我们先认识两个重要的堆算法。(下面这两种算法我们均以大堆为例)

 堆的向上调整算法

以大堆为例,堆的向上调整算法就是在大堆的末尾插入一个数据后,经过一系列的调整,使其仍然是一个大堆。

调整的基本思想如下:
1、将目标结点与其父结点进行比较。
2、若目标结点的值比父结点的值大,则交换目标结点与其父结点的位置,并将原目标结点的父结点当作新的目标结点继续进行向上调整;若目标结点的值比其父结点的值小,则停止向上调整,此时该树已经是大堆了。 

例如,现在我们在该大堆的末尾插入数据88。

 我们先将88与其父结点54进行比较,发现88比其父结点大,则交换父子结点的数据,并继续进行向上调整。

 此时将88与其父结点87进行比较,发现88还是比其父结点大,则继续交换父子结点的数据,并继续进行向上调整。

 这时再将88与其父结点89进行比较,发现88比其父结点小,则停止向上调整,此时该树已经就是大堆了。

 

堆的向上调整算法代码:

//堆的向上调整(大堆)
void AdjustUp(vector<int>& v, int child)
{
	int parent = (child - 1) / 2; //通过child计算parent的下标
	while (child > 0)//调整到根结点的位置截止
	{
		if (v[parent] < v[child])//孩子结点的值大于父结点的值
		{
			//将父结点与孩子结点交换
			swap(v[child], v[parent]);
			//继续向上进行调整
			child = parent;
			parent = (child - 1) / 2;
		}
		else//已成堆
		{
			break;
		}
	}
}

堆的向下调整算法 

 以大堆为例,使用堆的向下调整算法有一个前提,就是待向下调整的结点的左子树和右子树必须都为大堆。

调整的基本思想如下:
1、将目标结点与其较大的子结点进行比较。
2、若目标结点的值比其较大的子结点的值小,则交换目标结点与其较大的子结点的位置,并将原目标结点的较大子结点当作新的目标结点继续进行向下调整;若目标结点的值比其较大子结点的值大,则停止向下调整,此时该树已经是大堆了。 

例如,将该二叉树从根结点开始进行向下调整。(此时根结点的左右子树已经是大堆)

 将60与其较大的子结点88进行比较,发现60比其较大的子结点小,则交换这两个结点的数据,并继续进行向下调整。

此时再将60与其较大的子结点87进行比较,发现60比其较大的子结点小,则再交换这两个结点的数据,并继续进行向下调整。

 

 这时再将60与其较大的子结点54进行比较,发现60比其较大的子结点大,则停止向下调整,此时该树已经就是大堆了。

 堆的向下调整算法代码:

//堆的向下调整(大堆)
void AdjustDown(vector<int>& v, int n, int parent)
{
	//child记录左右孩子中值较大的孩子的下标
	int child = 2 * parent + 1;//先默认其左孩子的值较大
	while (child < n)
	{
		if (child + 1 < n&&v[child] < v[child + 1])//右孩子存在并且右孩子比左孩子还大
		{
			child++;//较大的孩子改为右孩子
		}
		if (v[parent] < v[child])//左右孩子中较大孩子的值比父结点还大
		{
			//将父结点与较小的子结点交换
			swap(v[child], v[parent]);
			//继续向下进行调整
			parent = child;
			child = 2 * parent + 1;
		}
		else//已成堆
		{
			break;
		}
	}
}

priority_queue的模拟实现

只要知道了堆的向上调整算法和堆的向下调整算法,priority_queue的模拟实现就没什么困难了。

priority_queue的模拟实现代码:

namespace zhc //防止命名冲突
{
	//比较方式(使内部结构为大堆)
	template<class T>
	struct less
	{
		bool operator()(const T& x, const T& y)
		{
			return x < y;
		}
	};
	//比较方式(使内部结构为小堆)
	template<class T>
	struct greater
	{
		bool operator()(const T& x, const T& y)
		{
			return x > y;
		}
	};
	//优先级队列的模拟实现
	template<class T, class Container = vector<T>, class Compare = less<T>>
	class priority_queue
	{
	public:
		//堆的向上调整
		void AdjustUp(int child)
		{
			int parent = (child - 1) / 2; //通过child计算parent的下标
			while (child > 0)//调整到根结点的位置截止
			{
				if (_comp(_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);
			AdjustUp(_con.size() - 1); //将最后一个元素进行一次向上调整
		}
		//堆的向下调整
		void AdjustDown(int n, int parent)
		{
			int child = 2 * parent + 1;
			while (child < n)
			{
				if (child + 1 < n&&_comp(_con[child], _con[child + 1]))
				{
					child++;
				}
				if (_comp(_con[parent], _con[child]))//通过所给比较方式确定是否需要交换结点位置
				{
					//将父结点与孩子结点交换
					swap(_con[child], _con[parent]);
					//继续向下进行调整
					parent = child;
					child = 2 * parent + 1;
				}
				else//已成堆
				{
					break;
				}
			}
		}
		//弹出队头元素(堆顶元素)
		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			AdjustDown(_con.size(), 0); //将第0个元素进行一次向下调整
		}
		//访问队头元素(堆顶元素)
		T& top()
		{
			return _con[0];
		}
		const T& top() const
		{
			return _con[0];
		}
		//获取队列中有效元素个数
		size_t size() const
		{
			return _con.size();
		}
		//判断队列是否为空
		bool empty() const
		{
			return _con.empty();
		}
	private:
		Container _con; //底层容器
		Compare _comp; //比较方式
	};
}

 

C++STL— priority_queue的使用与模拟实现内容到此介绍结束了,感谢您的阅读!!!

如果内容对你有帮助的话,记得给我点个赞——做个手有余香的人。感谢大家的支持!!!

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

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

相关文章

极米十年巅峰之作极米Z7X,能带走的百吋大屏

近年来&#xff0c;随着人们娱乐消费的升级&#xff0c;家用投影仪消费市场不断扩大&#xff0c;增长速度也非常可观。据IDC最新发布的数据显示&#xff0c;2022年中国投影机市场总出货量505万台&#xff0c;同比增长7.4%。其中&#xff0c;智能投影机市场&#xff08;搭载有OS…

ChatGPT:免费可用 ChatGPT 网页版(免登录、免注册、不限制使用次数)

一、什么是chatgpt ChatGPT是一种基于GPT-3(Generative Pre-trained Transformer 3)的聊天机器人。GPT-3是由OpenAI公司开发的自然语言处理模型&#xff0c;具有非常强的语言理解和生成能力。 ChatGPT使用了GPT-3的预训练模型&#xff0c;在此基础上进行了微调和优化&#xf…

机器学习:基于Apriori算法对中医病症辩证关联规则分析

系列文章目录 作者&#xff1a;i阿极 作者简介&#xff1a;Python领域新星作者、多项比赛获奖者&#xff1a;博主个人首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#xff0c;可以点赞&#x1f44d;收藏&#x1f4c1;评论&#x1f4d2;关注…

【Linux】进程间通信的有关基础概念

在以前我们使用多进程时&#xff0c;我们一般都是让父子进程分别执行各自的代码&#xff0c;进程之间几乎没有通信&#xff0c;但是实际过程中&#xff0c;进程间的通信是十分重要的的一件事情&#xff0c;一个复杂的程序一般都是有多个进程相互通信&#xff0c;协调进行来完成…

重磅发布 |《2023年消费品企业数字化转型调研白皮书》

数字经济时代&#xff0c;数字化转型对于消费品企业越来越重要&#xff0c;已成为消费品企业增加经济效益、提升竞争力的重要策略之一。随着数字化转型进入深水区&#xff0c;越来越多涉及到商业模式、业务模式和产业链生态的创新变革开始出现&#xff0c;给消费品企业带来了一…

【UE】windows包蓝图分辨率设置

【UE】windows包蓝图分辨率设置 屏幕模式&#xff08;SetFullscreenMode&#xff09; 模式说明全屏可以任意修改分辨率的全屏窗口化全屏适配显示器分辨率的全屏窗口化窗口化 分辨率修改方法(SetScreenResolution) 控制台修改分辨率方法(ExecuteConsoleCommand) 命令 &#xf…

股票量化分析工具QTYX使用攻略——挖掘主升浪中的人气个股(更新2.6.5)

搭建自己的量化系统 如果要长期在市场中立于不败之地&#xff01;必须要形成一套自己的交易系统。 行情不等人&#xff01;边学习边实战&#xff0c;在实战中学习才是最有效地方式。于是我们分享一个即可以用于学习&#xff0c;也可以用于实战炒股分析的量化系统——QTYX。 QTY…

如何有效运用测评自养号来提升阿里国际店铺权重

在阿里国际平台上提升销售并非易事&#xff0c;但是借助强大的营销策略和有效的自养号技术&#xff0c;你可以大幅度提升你的店铺销量。以下是一些具体的步骤和技巧。 1. 数据分析和市场调研 首先&#xff0c;要了解你的目标客户群体和市场趋势。分析你的销售数据&#xff0c…

chatgpt赋能python:Python编程教程:使用Python生成0到100的列表

Python编程教程&#xff1a;使用Python生成0到100的列表 Python是一种流行的编程语言&#xff0c;因其简单易学、强大而受到广泛欢迎。本文将介绍如何使用Python编程语言来生成0到100的数字列表。 什么是Python? Python是一种高级编程语言&#xff0c;由Guido van Rossum 在…

PHP+vue高校教学考研资料分享系统

运行环境:phpstudy/wamp/xammp等 开发语言&#xff1a;php 后端框架&#xff1a;Thinkphp5 前端框架&#xff1a;vue.js 服务器&#xff1a;apache 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat/phpmyadmin用户首次登录系统需要注册一个用户&#xff0c;用户在登陆平…

day4-项目软硬件环境分析和通讯结构体

硬件部分 fs4412开发板 3*zigbee模块 摄像头 gprs&#xff08;用于通讯&#xff09; fs4412部分 3个USB接口分别用于zigbee协调器、usb摄像头、gprs模块 陀螺仪与加速计作为数据采集端&#xff0c;发送到HTML USB-OTG用于安卓下载 电位器用于测量电压 蜂鸣器基于PWM来…

【LeetCode中等】二进制矩阵中的最短路径

给你一个 n x n 的二进制矩阵 grid 中&#xff0c;返回矩阵中最短 畅通路径 的长度。如果不存在这样的路径&#xff0c;返回 -1 。 二进制矩阵中的 畅通路径 是一条从 左上角 单元格&#xff08;即&#xff0c;(0, 0)&#xff09;到 右下角 单元格&#xff08;即&#xff0c;(…

在TP6.0引入Bootstrap4分页样式

1. TP6.0 默认分页 默认分页驱动类文件 vendor/topthink/think-orm/src/paginator/driver/Bootstrap.php 默认分页代码 <ul class"pagination"> <li><a href"?page1">&laquo;</a></li> <li><a hre…

​Win10更新清理怎么做?

“我有一台华硕二合一笔记本电脑&#xff0c;发现它开始运行缓慢。有时&#xff0c;屏幕会卡在加载界面上&#xff0c;不得不重新启动。为了让电脑更加流畅&#xff0c;我已经将其更新到Windows 10版本&#xff0c;现在希望通过Win10更新清理来进一步提升性能。请问如何进行Win…

电脑重装win11系统好还是win10好

随着Windows 11的发布&#xff0c;许多用户开始思考&#xff0c;是应该升级到Windows 11还是继续使用Windows 10&#xff1f;本文将为您比较Windows 11和Windows 10的优势与劣势&#xff0c;帮助您选择适合自己的操作系统。 工具/原料&#xff1a; 系统版本&#xff1a;window…

Windows Copilot,来了!

公众号关注 “GitHubDaily” 设为 “星标”&#xff0c;每天带你逛 GitHub&#xff01; 5 月 23 日&#xff0c;微软 2023 Build 开发者大会正式开幕&#xff0c;跟 Google I/O 和 Apple WWDC 一样&#xff0c;每年微软都会在 Build 大会上发布各种新产品。 由于最近几个月 Cha…

CNNs和视觉Transformer:分析与比较

探索视觉Transformer和卷积神经网络&#xff08;CNNs&#xff09;在图像分类任务中的有效性。 图像分类是计算机视觉中的关键任务&#xff0c;在工业、医学影像和农业等各个领域得到广泛应用。卷积神经网络&#xff08;CNNs&#xff09;是该领域的一项重大突破&#xff0c;被广…

软考网工计算题总结(一):总共33类题型,进来复习啦!

题型一&#xff1a; 1.地址编号从80000H到BFFFFH且按字节编址的内存容量为&#xff08;5&#xff09;KB,若用16KX4bit的存储芯片够成该内存&#xff0c;共需&#xff08;6&#xff09;片。 (5)A.128 B.256 C.512 D.1024 (6)A.8 B.16 C.32 D.64 【答案】B C 【解析】本题…

springboot入门简单使用

springboot入门简单使用 1、SpringBoot项目创建并配置mysql数据库创建项目编写Controller测试配置数据库 2、SpringBoot集成mybatis-plus初始化数据库安装mybatis-plus通过mybatis-plus将数据库数据通过接口显示 3、SpringBoot三层架构Controller、Service、Dao4、SpringBoot集…

【鲁棒、状态估计】用于电力系统动态状态估计的鲁棒迭代扩展卡尔曼滤波器研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…