【C++打怪之路Lv11】-- stack、queue和优先级队列

🌈 个人主页:白子寰
🔥 分类专栏:重生之我在学Linux,C++打怪之路,python从入门到精通,数据结构,C语言,C语言题集👈 希望得到您的订阅和支持~
💡 坚持创作博文(平均质量分82+),分享更多关于深度学习、C/C++,python领域的优质内容!(希望得到您的关注~)

目录

C++为什么要学习stack、queue和优先级队列

stack类

stack类的介绍

stack的基本操作

stack的模拟实现

 queue类

queue类的介绍

queue的基本操作

queue的模拟实现

 优先级队列

优先级队列的介绍

仿函数 

什么是仿函数 

为什么要有仿函数 

优先级队列的使用

成员函数

 排序准则

优先级队列的模拟实现

关于容器适配器


C++为什么要学习stack、queue和优先级队列

学习C++中的栈(stack)、队列(queue)和优先级队列(priority queue)对开发者来说非常重要,因为它们是常用的数据结构,在解决各种编程问题时提供了高效的方法。

以下是它们的核心作用和特点:

1. 栈(Stack)
   特点后进先出(LIFO),即最后入栈的元素最先出栈。
   应用:适用于函数调用、表达式求值、撤销操作等场景。例如,程序在执行递归调用时会用栈来存储函数状态。

2. 队列(Queue)
   特点先进先出(FIFO),即最先进入队列的元素最先被处理。
   应用:适用于任务调度、消息处理、广度优先搜索等需要按顺序处理数据的场景。

3. 优先级队列(Priority Queue):
   特点:元素按优先级排序,每次取出的是优先级最高的元素,而不是按插入顺序。
   应用:适用于任务管理(例如操作系统中的任务调度)、最短路径算法(如Dijkstra算法)、数据流中找出Top K元素等场景。

这些数据结构在C++中有标准库支持(如`<stack>`、`<queue>`和`<priority_queue>`),可以帮助开发者更高效地处理特定类型的问题,提高程序的可读性和性能。


stack类

stack类的介绍

stack 是 C++ 标准模板库(STL)中的一个容器适配器,用于实现后进先出(LIFO)数据结构。

基于其他序列容器(如 dequevectorlist)构建,默认使用 deque 作为底层容

stack<int, vector<int>> st;

注:

1、定义了一个名为 st 的栈(stack)

其中包含 int 类型的元素,并使用 vector<int> 作为其底层容器

2、stack 默认使用 deque 作为底层容器,但可以通过这种方式替换成其他容器

3、特点 & 好处

  • 该栈 st 仍然保持 stack 的 后进先出 特性。
  • 使用 vector 作为底层容器意味着栈的元素实际上存储在一个 vector 中,但只能通过 stack 提供的接口(如 push()pop()top() 等)访问。

这样做的优势在于,如果对底层容器的特性(如内存管理或其他特定操作)有特殊需求,可以灵活选择适合的容器


stack的基本操作

  • push()将元素压入栈顶
  • pop()移除栈顶元素
  • top():返回栈顶元素的引用只能访问栈顶元素(通过 top()),无法直接访问其他位置的元素
  • empty():判断栈是否为空
  • size():返回栈中元素的个数


stack的模拟实现

namespace sky
{
	template<class T, class Container = vector<int>>
	class Stack
	{
	public:
		void push(const T& val)
		{
			_con.push_back(val);	// 压栈插入数据
		}

		void pop()
		{
			_con.pop_back();		// 删除用尾删
		}

		const T& top()
		{
			return _con.back();		// 后进先出
		}

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

		size_t size()
		{
			return _con.size();
		}
	private:
		Container _con;
	};
}

int main()
{
	sky::Stack<int,vector<int>>	st;
	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);
	st.push(5);

	cout << st.size() << endl;

	while (!st.empty())
	{
		cout << st.top() << " ";
		st.pop();
	}
	cout << endl;

	return 0;
}


 queue类

queue类的介绍

1、queue 是标准库容器适配器,用于实现先进先出(FIFO)队列。

它基于底层容器(如 dequelist)进行封装

2、默认使用 deque 作为存储容器,也可以指定其他符合双端操作要求的容器。

queue 适用于需要按顺序处理数据的场景,如任务调度或广度优先搜索等


queue的基本操作

  • push():向队尾添加元素
  • pop()移除队头元素
  • front():返回队头元素的引用
  • back():返回队尾元素的引用
  • empty()检查队列是否为空
  • size():返回队列中元素的数量

 


queue的模拟实现

namespace sky
{
	template<class T, class Container = list<int>>
	class Queue
	{
	public:
		void push(const T& val)
		{
			_con.push_back(val);
		}

		void pop()
		{
			_con.pop_front();
		}

		T& front()
		{
			return _con.front();
		}

		T& back()
		{
			return _con.back();
		}

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

		size_t size()
		{
			return _con.size();
		}
	private:
		Container _con;
	};
}

int main()
{
	sky::Queue<int> q;
	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);

	cout << q.back() << endl;

	cout << q.size() << endl;
	while (!q.empty())
	{
		cout << q.front() << " ";
		q.pop();
	} 

	return 0;
}


 优先级队列

优先级队列的介绍

priority_queue 是标准库容器适配器,用于实现优先级队列,其元素根据优先级自动排序。默认情况下,它使用最大堆结构,使得队头元素总是优先级最高的元素

priority_queue 适用于需要动态维护最大(或最小)元素的场景,如任务调度、路径规划等

注:需要包头文件<queue>


仿函数 

什么是仿函数 

priority_queue的函数原型比queuestack多了一个参数,用于指定比较函数,这个参数决定了元素在priority_queue中的排序方式

比较函数(仿函数)priority_queue需要一个比较函数(通常是仿函数)来定义元素之间的优先级顺序。默认情况下,它使用std::less<T>,这意味着它将按照从小到大的顺序排列,形成一个最大堆

这是priority_queuequeuestack最显著的区别,因为priority_queue需要根据元素的优先级来组织数据,而queuestack仅需要遵循基本的先进先出或后进先出原则


为什么要有仿函数 

  • 自定义比较逻辑:优先级队列默认情况下是一个最大堆,即最大的元素具有最高的优先级。但有时我们可能需要根据不同的标准来排序元素,比如最小堆或者基于对象的某个成员函数。通过使用仿函数,我们可以自定义比较逻辑,使得优先级队列能够按照我们期望的顺序排列元素。
  • 状态保持:仿函数可以保持状态,这意味着它们可以在调用之间保留信息,这在某些复杂的比较逻辑中非常有用。
  • 类型安全:使用仿函数可以保证类型安全,因为编译器会在编译时检查传递给仿函数的参数类型是否正确。

优先级队列的使用

成员函数

  • push()插入元素,并自动调整位置
  • pop()移除优先级最高的元素(队头)
  • top()访问优先级最高的元素
  • empty():检查队列是否为空。
  • size():返回元素的数量

 排序准则

默认使用 std::less(大顶堆),可以通过自定义比较函数来实现小顶堆或其他排序


优先级队列的模拟实现

namespace sky
{
	template<class T>
	class less
	{
	public:
		bool operator()(const T& x, const T& y)
		{
			// 在构建堆时,x < y 的意思是:如果 x 比 y 小,
			// 那么 x 的优先级低于 y,所以 y 应该排在 x 前面
			return x < y;
		}
	};

	template<class T>
	class greater
	{
	public:
		// 当使用 greater 作为比较器时,较小的元素会排在前面,因此可以创建一个"最小优先队列"
		bool operator()(const T& x, const T& y)
		{
			return x > y;
		}
	};

	template<class T, class Container = vector<int>, class Compare = less<T>>
	class priority_queue
	{
	public:
		void adjust_up(int child)
		{
			Compare com;
			int parent = (child - 1) / 2;
			while (child > 0)
			{
				// 如果父节点的值比子节点的值小,则交换(基于比较器的定义)
				if (com(_con[parent], _con[child]))
				{
					swap(_con[parent], _con[child]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

		void adjust_down(int parent)
		{
			Compare com;
			int child = parent * 2 + 1;
			while (child < _con.size())
			{
				// 如果有右子节点且右子节点比左子节点大,则选择右子节点
				if (child + 1 < _con.size() && com(_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 push(const T& val)
		{
			 _con.push_back(val);
			 adjust_up(_con.size() - 1);
		}

		// 删除堆顶元素并调整堆
		void pop()
		{
			if (!_con.empty())
			{
				swap(_con[0], _con[_con.size() - 1]);
				_con.pop_back();
				adjust_down(0);
			}
		}

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

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

		size_t size() const
		{
			return _con.size();
		}
	private:
		Container _con;
	};
}

int main()
{
	sky::priority_queue<int> pq;
	pq.push(3);
	pq.push(1);
	pq.push(5);
	pq.push(4);
	pq.push(2);

	while (!pq.empty())
	{
		cout << pq.top() << " ";
		pq.pop();
	}
	cout << endl;

	return 0;
}

关于容器适配器


***********************************************************分割线*****************************************************************************
完结!!!
感谢浏览和阅读。

等等等等一下,分享最近喜欢的一句话:

“把自己活出一道光”。

我是白子寰,如果你喜欢我的作品,不妨你留个点赞+关注让我知道你曾来过。
你的点赞和关注是我持续写作的动力!!! 
好了划走吧。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于SSM+微信小程序的家庭记账本管理系统(家庭1)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 1、管理员端功能有首页、个人中心、用户管理&#xff0c;消费详情管理、收入详情管理、系统管理等。 2、用户端功能有首页、消费详情、收入详情、论坛信息、我的等功能。 2、项目技术 …

C语言教程——数组(1)

目录 系列文章目录 前言 1、一维数组的创建和初始化 1.1数组的创建 1.2数组的初始化 1.3一维数组的使用 总结 1.4一维数组在内存中的存储 2、二维数组的创建和初始化 2.1二维数组的创建 2.2二维数组的初始化 2.3二维数组的使用 2.4二维数组在内存中的存储 3、数组…

时空智友企业流程化管控系统uploadStudioFile接口存在任意文件上传漏洞

免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用。 1. 时空智友…

【Vulnhub靶场】Kioptrix Level 3

目标 本机IP&#xff1a;192.168.118.128 目标IP&#xff1a;192.168.118.0/24 信息收集 常规 nmap 扫存活主机&#xff0c;扫端口 根据靶机IP容易得出靶机IP为 192.168.118.133 nmap -sP 192.168.118.0/24nmap -p- 192.168.118.133 Getshell 开放22端口和80 端口 访问web…

C++进阶之路:日期类的实现、const成员(类与对象_中篇)

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

如何选择合适的云服务商,看IDC怎么说

01 | 2份IDC报告&#xff0c;评估了Covid后的云增长与云服务市场的变化 《IDC MarketScape&#xff1a;全球公有云基础设施即服务提供商评估》&#xff08;2022&#xff09;共评估了 13 家云提供商&#xff0c;其中既有超大规模云服务商&#xff0c;如亚马逊云科技&#xff1b…

论文阅读-三维结构几何修复(导-4)

摘要 解决了3D数字模型中大洞修复的问题。 通过基于字典学习的方法解决了缺失区域推断问题&#xff0c;该方法利用从单个自相似结构和在线深度数据库中得出的几何先验。利用几何先验提供的线索&#xff0c;从洞的边界周围自适应地传播局部3D表面平滑性来恢复底层表面。在合成…

word中的内容旋转90度

在vsto、Aspose.Words 中&#xff0c;默认没有直接的 API 可以让表格整体旋转 90 度。然而&#xff0c;我们可以通过一些方式来实现类似的效果&#xff0c;具体思路如下&#xff1a; 将表格插入到一个形状&#xff08;Shape&#xff09;或文本框中&#xff0c;然后旋转该形状。…

使用Docker启动的Redis容器使用的配置文件路径等问题以及Python使用clickhouse_driver操作clickhouse数据库

一、使用Docker启动的Redis容器使用的配置文件路径等问题 1.docker启动的redis使用的配置文件路径是什么 使用docker搭建redis服务&#xff0c;本身redis启动的时候可以指定配置文件的&#xff0c; redis-server /指定配置文件路径/redis.conf。 但手上也没有一个redis配置文件…

【Golang】合理运用泛型,简化开发流程

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

灵动AI视频最新AIGC 系统:支持多种模型切换 支持5端部署

灵动AI视频官网地址&#xff1a;https://aigc.genceai.com/

SeCo复现

表1 复现结果–CAM&#xff1a;74.751 Mask&#xff1a;76.47 Val&#xff1a;74.0 Test&#xff1a;73.7948&#xff0c;完全一致 表3 复现结果&#xff1a;0.233&#xff0c;完全一致 感想 第10篇完全复现的论文

知识点框架笔记3.0笔记

如果基础太差&#xff0c;搞不清基本交规的&#xff08;模考做不到60分&#xff09;&#xff0c;建议找肖肖或者小轩老师的课程看一遍&#xff0c;内容差不多&#xff08;上面有链接&#xff09;&#xff0c;笔记是基于肖肖和小轩老师的科目一课程以及公安部交管局法规&#xf…

京东笔试题

和谐敏感词 &#x1f517; 题目地址 &#x1f389; 模拟 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);int n scanner.nextInt();String s scanner.next();String[] words new String[…

Android GPU Inspector分析帧数据快速入门

使用 谷歌官方工具Android GPU Inspector (AGI) 可以对Android 应用进行深入和全面的系统性能分析和帧性能分析 。AGI 是一个非常强大的分析工具&#xff0c;尤其是在需要诊断 GPU 性能问题和优化应用时&#xff0c;可以帮助你精准找到性能瓶颈。本文介绍如何使用该工具对帧数据…

Docker 安装Postgres和PostGIS,并制作镜像

1. 查找postgres和postgis现有的镜像和版本号 镜像搜索网站&#xff1a;https://docker.aityp.com/ 测试使用的是postgres:15.4 和 postgis:15-3.4 2、镜像拉取 docker pull postgres:15.4docker pull postgis/postgis:15-3.4镜像下载完成&#xff0c;docker images 查看如…

CentOS7安装RabbitMQ-3.13.7、修改端口号

本文安装版本&#xff1a; Erlang&#xff1a;26.0 官网下载地址 Erlang RabbitMQ&#xff1a;3.13.7 官网下载地址 RabbitMQ RabbitMQ和Erlang对应关系查看&#xff1a;https://www.rabbitmq.com/which-erlang.html 注&#xff1a;安装erlang之前先安装下依赖文件&#xff0…

【Hive】8-Hive性能优化及Hive3新特性

Hive性能优化及Hive3新特性 Hive表设计优化 Hive查询基本原理 Hive的设计思想是通过元数据解析描述将HDFS上的文件映射成表 基本的查询原理是当用户通过HQL语句对Hive中的表进行复杂数据处理和计算时&#xff0c;默认将其转换为分布式计算 MapReduce程序对HDFS中的数据进行…

软件测试学习笔记丨Linux三剑客-sed

本文转自测试人社区&#xff0c;原文链接&#xff1a;https://ceshiren.com/t/topic/32521 一、简介 sed&#xff08;Stream editor&#xff09;是一个功能强大的文本流编辑器&#xff0c;主要用于对文本进行处理和转换。它适用于自动化处理大量的文本数据&#xff0c;能够支持…

九、pico+Unity交互开发——触碰抓取

一、VR交互的类型 Hover&#xff08;悬停&#xff09; 定义&#xff1a;发起交互的对象停留在可交互对象的交互区域。例如&#xff0c;当手触摸到物品表面&#xff08;可交互区域&#xff09;时&#xff0c;视为触发了Hover。 Grab&#xff08;抓取&#xff09; 概念&#xff…