【priority_queue的使用及模拟实现】—— 我与C++的不解之缘(十六)

news2024/11/20 4:55:25

前言

​ priority_queue,翻译过来就是优先级队列,但是它其实是我们的堆结构(如果堆一些遗忘的可以看一下前面的文章复习一下【数据结构】二叉树——顺序结构——堆及其实现_二叉树顺序结构-CSDN博客),本篇文章就来使用并且模拟实现一下priority_queue。

priority_queue的使用

在这里插入图片描述

​ 这个容器接口就这些,使用起来比较简单:这里就简单使用一下。

int main()
{
	priority_queue<int> pq1;//无参构造
	int arr[] = { 1,5,8,9,2,10,6 };
	//使用一段迭代器区间构造(这里可以使用数组,因为原始指针可以像迭代器那样使用)
	priority_queue<int> pq2(arr, arr + sizeof(arr) / sizeof(arr[0]));
	//依次输出pq2
	while (!pq2.empty())
	{
		cout << pq2.top() << " ";
		pq2.pop();
	}
	cout << endl;
	
	//往pq1插入数据
	pq1.push(1);
	pq1.push(5);
	pq1.push(7);
	pq1.push(8);
	pq1.push(9);
	//依次输出pq1
	while (!pq1.empty())
	{
		cout << pq1.top() << " ";
		pq1.pop();
	}
	cout << endl;
	return 0;
}

输出结果如下:

10 9 8 6 5 2 1
9 8 7 5 1

​ 经过观察,我们会发现,默认构建的都是大堆,先看一下容器priority_queue 的定义

在这里插入图片描述

​ 这里有三个模版参数,第一个是数据类型,第二个是容器类型(默认是vector),第三个是compare 默认是 less(这个是一个仿函数,再模拟实现后面再讲解)。

我们不难发现,只有第三个模版参数才也可能控制是大堆还是小堆,(这里,我们如果要建小堆传**greater**即可)。

//建小堆
int main()
{
	priority_queue<int, vector<int>, greater<int>> pq1;
	pq1.push(9);
	pq1.push(7);
	pq1.push(5);
	pq1.push(3);
	pq1.push(2);
	while (!pq1.empty())
	{
		cout << pq1.top() << " ";
		pq1.pop();
	}
	cout << endl;
	return 0;
}
2 3 5 7 9

​ 这样就建了小堆;对于仿函数,在模拟实现之后,我相信就会有了深刻的理解。

priority_queue模拟实现

​ 通过看priority_queue的定义,我们不难发现其也是一个容器适配器,默认容器是vector;所以它的成员变量就是一个容器,其的每一个操作就是在容器中进行一系列操作。

先来看一下priotity_queue的大致内容:

namespace HL
{
	//默认——大堆
	template<class T, class Contianer = vector<T>, class Compare = less<T>>
	class priority_queue
	{
		//向下调整算法
		void AdjustDown(int parent)
		{}
		//向上调整算法
		void AjustUp(int child)
		{}
	public:
		//默认构造
		priority_queue() {}
		//迭代器区间构造
		template<class InputIterator>
		priority_queue(InputIterator first, InputIterator last)
		{}
		void push(const T& x) {}
		void pop() {}
		T& top() {}
		const T& top()const {}
		size_t size()const {}
		bool empty()const {}
	private:
		Contianer _con;
	};
}

1、向上调整算法

​ 所谓向上调整算法,就是向上调整当前节点,使其满足堆结构。

主要应用:插入节点时,最后一个节点(插入的节点)向上调整。

		//向上调整算法
		void AjustUp(int child)
		{
			int parent = (child - 1) / 2;
			while (parent >= 0)
			{
				if (_con[parent] < _con[child])
				{
					std::swap(_con[parent], _con[child]);
				}
				else
				{
					break;
				}
				child = parent;
				parent = (child - 1) / 2;
			}
		}

2、向下调整算法

​ 所谓向上调整算法,就是向下调整当前节点,使其满足堆结构。

主要应用:

  • 构造堆结构时,从最后一个节点的父节点开始依次向下调整,创建堆结构。
  • 删除节点时,第一个(堆顶)与最后一个(堆底)交换,然后让第一个(堆顶)节点向下调整。
    在这里插入图片描述
		void AdjustDown(int parent)
		{
			int child = 2 * parent + 1;
			while (child < _con.size())
			{
				if (child < _con.size() - 1 && _con[child] < _con[child + 1])
				{
					child++;
				}
				if (_con[parent] < _con[child])
				{
					std::swap(_con[parent], _con[child]);
				}
				else
				{
					break;
				}
				parent = child;
				child = 2 * parent + 1;
			}
		}

3、构造函数

​ 构造函数有两种,一是默认构造函数,另一个就是使用迭代器区间构造。

1.默认构造

//默认构造
priority_queue() {}

2.迭代器区间构造

​ 迭代器区间,这里就先将数据插入到容器(vector)中,再从最后一个节点的父节点开始,依次往下调整建堆即可。

//迭代器区间构造
template<class InputIterator>
priority_queue(InputIterator first, InputIterator last)
{
	while (first != last)
	{
		_con.push_back(*first);
		++first;
	}
	for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(i);
	}
}	

4、push、pop、top

  • push: 插入数据,然后向上调整,保持堆结构。
void push(const T& x) 
{
	_con.push_back(x);
	AdjustUp(_con.size() - 1);
}
  • pop: 删除数据(删除堆顶数据),堆顶数据与堆低数据交换,然后从堆顶位置向下调整即可。
void pop() 
{
	std::swap(_con[0], _con[_con.size() - 1]);
	AdjustDown(0);
}
  • top: 返回堆顶数据
T& top() 
{
	return _con[0];
}
const T& top()const 
{
	return _con[0];
}

5、size、empty、swap

  • size: 返回堆中的数据个数
size_t size()const 
{
	return _con.size();
}
  • empty: 判断堆是否为空
bool empty()const 
{
	return _con.empty();
}
  • swap: 交换函数
void swap(priority_queue& pq)
{
	std::swap(_con, pq._con);
}

​ 到这里,priority_queue 大致就实现成功了一半,因为这里我们只实现了大堆。

接下来,我们来看一下仿函数,如何实现大小堆。

仿函数

​ 仿函数,也是STL中比较中要的内容;

那为什么叫做仿函数呢?因为,他实际上是一个类,这个类重载了operator() 这样,我们就可以像函数应用实使用这个类。

先来看一下仿函数**less**:

	//这里可以使用struct(默认成员是共有)
	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;
		}
	};

​ 这里实现了仿函数**Less** 和**Greater**,我们可以像函数那样去使用这个类。

int main()
{
	HL::Less<int> l;
	cout << (l(11, 22)) << endl;
	return 0;
}

greater 与less类似,greater 是判断大的(就是,返回的是 x>y)。

​ 知道了仿函数,再回头看一下**priority_queue** 第三个模板参数,这个模板参数就是来控制大小堆的(默认是less,就是大堆;如果我们传greater 就是小堆。)

这样我们再修改一下,向上调整算法和向下调整算法,让我们可以通过这个模板参数来控制大小堆。

		//向下调整算法
		void AdjustDown(int parent)
		{
			Compare com;
			int child = 2 * parent + 1;
			while (child < _con.size())
			{
				//if (child < _con.size() - 1 && _con[child] < _con[child + 1])
				if (child < _con.size() - 1 && com(_con[child], _con[child + 1]))
				{
					child++;
				}
				//if (_con[parent] < _con[child])
				if (com(_con[parent] , _con[child]))
				{
					std::swap(_con[parent], _con[child]);
				}
				else
				{
					break;
				}
				parent = child;
				child = 2 * parent + 1;
			}
		}
		//向上调整算法
		void AdjustUp(int child)
		{
			Compare com;
			int parent = (child - 1) / 2;
			while (parent >= 0)
			{
				//if (_con[parent] < _con[child])
				if (com(_con[parent] , _con[child]))
				{
					std::swap(_con[parent], _con[child]);
				}
				else
				{
					break;
				}
				child = parent;
				parent = (child - 1) / 2;
			}
		}

​ 这里测试一下,使用模拟实现的堆进行排序,pq1建大堆,排降序;pq2建小堆,排升序。

void test_priority_queue()
{
	HL::priority_queue<int,vecotr<int>, HL::Less<int>> pq1;
	pq1.push(1);
	pq1.push(7);
	pq1.push(3);
	pq1.push(5);
	pq1.push(9);

	while (!pq1.empty())
	{
		cout << pq1.top() << " ";
		pq1.pop();
	}
	cout << endl;
	int arr[] = { 1,3,5,7,9,8,6,4,2 };
	HL::priority_queue<int,vector<int>,HL::Greater<int>> pq2(arr, arr + sizeof(arr) / sizeof(arr[0]));
	while (!pq2.empty())
	{
		cout << pq2.top() << " ";
		pq2.pop();
	}
	cout << endl;
}
int main()
{
	test_priority_queue();
	return 0;
}
9 7 5 3 1
1 2 3 4 5 6 7 8 9

​ 到这里,priority_queue 使用以及模拟实现就完成了,感谢各位的支持。

继续加油!!!

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws

Greater<int>> pq2(arr, arr + sizeof(arr) / sizeof(arr[0]));
	while (!pq2.empty())
	{
		cout << pq2.top() << " ";
		pq2.pop();
	}
	cout << endl;
}
int main()
{
	test_priority_queue();
	return 0;
}
9 7 5 3 1
1 2 3 4 5 6 7 8 9

到这里,priority_queue 使用以及模拟实现就完成了,感谢各位的支持。

继续加油!!!

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws

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

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

相关文章

在AndroidStudio中新建项目时遇到的Gradle下载慢问题,配置错的按我的来,镜像地址不知道哪个网页找的,最主要下载要快

android-studio-2024.2.1.11-windows Android 移动应用开发者工具 – Android 开发者 | Android Developers https://r4---sn-j5o76n7z.gvt1-cn.com/edgedl/android/studio/install/2024.2.1.11/android-studio-2024.2.1.11-windows.exe?cms_redirectyes&met1731775…

《Java核心技术 卷I》用户界面中首选项API

首选项API 在桌面程序中&#xff0c;通常都会存储用户首选项&#xff0c;如用户最后处理的文件、窗口的最后位置等。 利用Properties类可以很容易的加载和保存程序的配置信息&#xff0c;但有以下缺点&#xff1a; 有些操作系统没有主目录概念&#xff0c;很难为匹配文件找到…

服务器数据恢复—raid5阵列故障导致上层系统分区无法识别的数据恢复案例

服务器数据恢复环境&#xff1a; 某品牌DL380服务器&#xff0c;服务器中三块SAS硬盘组建了一组raid5阵列。服务器安装Windows Server操作系统&#xff0c;划分了3个分区&#xff0c;D分区存放数据库&#xff0c;E分区存放数据库备份。 服务器故障&#xff1a; RAID5阵列中有一…

Linux_shell脚本if语句详细教程

前言 在 Linux Shell 脚本中&#xff0c;if 语句用于基于条件执行命令或代码块。它的基本语法结构如下&#xff1a; if 条件; then# 如果条件为真时执行的代码 elif 另一个条件; then# 如果另一个条件为真时执行的代码 else# 如果所有条件都不成立时执行的代码 fi一、if 语句…

java中设计模式的使用(持续更新中)

概述 设计模式的目的&#xff1a;编写软件过程中&#xff0c;程序员面临着来自耦合性&#xff0c;内聚性以及可维护性&#xff0c;可扩展性&#xff0c;重用性&#xff0c;灵活性等多方面的挑战&#xff0c;设计模式是为了让程序&#xff08;软件&#xff09;&#xff0c;具有…

Leetcode 有效的数独

这段代码解决的是 验证一个数独是否有效 的问题&#xff0c;其算法思想是基于 规则校验和状态记录。具体思想如下&#xff1a; 算法思想 核心目标&#xff1a; 检查每个数字在 同一行、同一列 和 同一个 3x3 子格 中是否重复。 状态记录&#xff1a; 使用 3 个布尔二维数组分别…

群控系统服务端开发模式-应用开发-前端文件格式功能开发

一、添加视图 在根目录下src文件夹下views文件夹下param文件夹下filedoc文件夹下&#xff0c;新建index.vue&#xff0c;代码如下 <template><div class"app-container"><div class"filter-container" style"float:left;">&l…

可认证数据资产合约标准协议(CMIDA-1)意见征集

标准背景 数据资产具备多维度的属性&#xff0c;涵盖行业特性、状态信息、资产类型、存储格式等。数据资产在不同流通主体之间可理解、可流通、可追溯、可信任的重要前提之一是存在统一的标准&#xff0c;缺失统一的标准&#xff0c;数据混乱冲突、一数多源、多样多类等问题将…

大数据-227 离线数仓 - Flume 自定义拦截器(续接上节) 采集启动日志和事件日志

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; 目前开始更新 MyBatis&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff0…

Solana应用开发常见技术栈

编程语言 Rust Rust是Solana开发中非常重要的编程语言。它具有高性能、内存安全的特点。在Solana智能合约开发中&#xff0c;Rust可以用于编写高效的合约代码。例如&#xff0c;Rust的所有权系统可以帮助开发者避免常见的内存错误&#xff0c;如悬空指针和数据竞争。通过合理利…

redis类型介绍

1. 字符串&#xff08;String&#xff09;&#xff1a; • 简介&#xff1a;最基础的数据类型&#xff0c;可以存储任何形式的字符串&#xff0c;包括文本数据和数字数据。 • 常用操作&#xff1a;SET、GET、INCR、DECR等。 2. 列表&#xff08;List&#xff09;&#xff1a; …

Pytest-Bdd-Playwright 系列教程(10):配置功能文件路径 优化场景定义

Pytest-Bdd-Playwright 系列教程&#xff08;10&#xff09;&#xff1a;配置功能文件路径 & 优化场景定义 前言一、功能文件路径的配置1.1 全局设置功能文件路径1.2. 在场景中覆盖路径 二、避免重复输入功能文件名2.1 使用方法2.2 functools.partial 的背景 三、应用场景总…

HarmonyOs鸿蒙开发实战(17)=>沉浸式效果第二种方案一组件安全区方案

1.沉浸式效果的目的 开发应用沉浸式效果主要指通过调整状态栏、应用界面和导航条的显示效果来减少状态栏导航条等系统界面的突兀感&#xff0c;从而使用户获得最佳的UI体验。 2.组件安全区方案介绍 应用在默认情况下窗口背景绘制范围是全屏&#xff0c;但UI元素被限制在安全区内…

构建安全的数据库环境:群晖NAS安装MySQL和phpMyAdmin详细步骤

文章目录 前言1. 安装MySQL2. 安装phpMyAdmin3. 修改User表4. 本地测试连接MySQL5. 安装cpolar内网穿透6. 配置MySQL公网访问地址7. 配置MySQL固定公网地址8. 配置phpMyAdmin公网地址9. 配置phpmyadmin固定公网地址 前言 本文将详细讲解如何在群晖NAS上安装MySQL及其数据库管理…

【c++丨STL】list的使用

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C、STL 目录 前言 list简介 一、list的默认成员函数 构造函数(constructor) 析构函数 赋值重载 二、list的迭代器接口 迭代器的功能分类 三、list的容量…

如何编译 Cesium 源码

如何编译 Cesium 源码 Cesium 是一个开源的 JavaScript 库&#xff0c;用于构建 3D 地球和地图应用程序。它提供了一套强大的 API 和工具&#xff0c;使开发者能够创建丰富的地理空间应用。本文将指导您如何从 GitHub 下载 Cesium 源码&#xff0c;并在本地进行编译。 TilesB…

实验5:网络设备发现、管理和维护

实验5&#xff1a;网络设备发现、管理和维护 实验目的及要求&#xff1a; 通过实验&#xff0c;掌握Cisco 路由器和交换机的IOS配置管理。自动从NTP服务器获取时间信息。能够利用TFTP服务器实现路由器和交换机配置文件的备份和恢复。同时验证CDP协议和LLDP协议的网络参数。完…

全志T113双核异构处理器的使用基于Tina Linux5.0——RTOS编译开发说明

3、RTOS编译开发说明 3.1、RTOS SDK与TinaLinux开发环境 RTOS SDK相关代码已集成到Tina Linux开发环境&#xff0c;Tina Linux开发环境下的rtos子目录即为RTOS开发环境。 ├──brandy ├──bsp ├──build ├──buildroot ├──build.sh >build/top_build.sh ├──…

汽车资讯新篇章:Spring Boot技术启航

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-04

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-04 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-04目录1. Alopex: A Computational Framework for Enabling On-Device Function Calls with LLMs摘要&#xff1a;研究背景&…