【C++】容器篇(三)—— stack的基本介绍及其模拟实现

news2025/1/31 11:18:48

前言:

在之前的学习中我们已经了解了 vector 和 list ,今天我将带领学习的是关于STL库中的 stack的学习!!!


目录

(一)基本介绍

1、基本概念

 2、容器适配器

(二)基本使用

(三)stack模拟实现

1、stack的使用

2、 模拟实现

(四)题目讲解

1、逆波兰表达式求值

(五)总结


(一)基本介绍

学过数据结构的小伙伴对于 stack 结构应该是不陌生的,最主要的特点便是遵循Last In First Out(LIFO)的规则,这意味着最近添加的项目将首先被删除。

1、基本概念

接下来,我们先从文档来认识,看文档中是如何描述的。

  • 链接如下:stack文档介绍

  1.  从上我们看出stack是STL库中的一种容器,它用于存储数据,并遵循Last In First Out(LIFO)的规则;
  2. 堆栈是一种容器适配器,stack在C++ STL库中实现为一个模板类,提供一组特定的成员函数来访问其元素。

 2、容器适配器

此时可能就有很多小伙伴比较好奇什么叫做 “容器适配器”了,在这里我简单的介绍一下:

  • ⚔️ 容器适配器(又叫配机器)是STL库中的一类容器,使用已有的容器类来实现适配器的功能,从而提供方便的数据结构 ⚔️

容器适配器包括三种:stackqueuepriority_queue(后两者在后面会给大家介绍

💨 容器适配器有如下特点:

  • 1. 使用现有容器类作为底层实现。
  • 2. 基于已有的功能来添加和删除元素(例如push()、pop()、top()等),适用于特定的应用场景。
  • 3. 通常具有限制和限制,可以有所优化。

💨 这些容器适配器通常用于特定的数据结构,并简化了它们的实现。以下是简要描述:

  • 1. stack:stack是一种LIFO(Last-In-First-Out)容器,只允许在容器的一端插入和删除元素。通过stack,我们可以快速、轻松地实现如撤销、反转等功能。
  • 2. queue:queue是一种FIFO(First-In-First-Out)容器,只允许在容器的一端插入元素,在容器的另一端删除元素。通过queue,我们可以快速、轻松地实现如模拟消息队列等功能。
  • 3. priority_queue:priority_queue是一个优先级队列,它存储一组具有优先级的值,并按照优先级从高到低排序。通过priority_queue,我们可以快速、轻松地实现如任务调度等功能。

总结来说,容器适配器是为了方便使用STL中的已有容器类而设计的。通过简洁的接口,容器适配器提供了更高层次的容器类,简化了某些数据结构的实现。


(二)基本使用

接下来,我先通过具体的使用来带大家先感受一下用法是如何的。

  • 具体如下:
void test_1()
{
	stack<int> str;

	// 在栈顶添加元素
	str.push(1);
	str.push(2);
	str.push(3);
	str.push(4);
	str.push(5);

	//栈顶元素
	if (!str.empty())
	{
		cout << str.top() << " " << str.size() << endl;;
	}


	// 从栈顶弹出元素
	str.pop();

	// 获取栈顶元素
	cout << str.top() << endl;

	// 检查栈是否为空
	if (str.empty())
	{
		cout << "Stack is empty" << endl;
	}
	else
	{
		cout << "Stack is not empty" << endl;
	}

	// 获取栈的大小
	cout << "Stack size is " << str.size() << endl;
}
  • 结果如下:

解释说明:

  • 1、在上述代码中,我们先往栈里面插入了5个元素;
  • 2、紧接着,我们就验证了开头说的说的是否符合后进先出的规则,最终结果也成功的表明了相应的观点;
  • 3、接下来,经过pop 操作之后,在打印栈顶元素,我们可以发现此时的结果为4,也符合相应的预期;
  • 4、接下来,就是对其的栈是否为空的基本判断,以及stack大小的计算操作。


(三)stack模拟实现

stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下 操作:

  • empty:判空操作
  • back:获取尾部元素操作
  • push_back:尾部插入元素操作
  • pop_back:尾部删除元素操作

💨 标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器, 默认情况下使用deque

1、stack的使用


 

2、 模拟实现

 💨 从栈的接口中可以看出,栈实际是一种特殊的vector,因此使用vector完全可以模拟实现stack。

  • 1️⃣push()
void push(const T& x)
{
	_vv.push_back(x);
}
  • 2️⃣pop()
void pop()
{
	if (!_vv.empty())
	{
		_vv.pop_back();
	}
}
  • 3️⃣top()
const T& top()
{
	return _vv.back();
}
  • 4️⃣empty()
bool empty()
{
	return _vv.empty();
}
  • 5️⃣size()
size_t size()
{
	return _vv.size();
}

整体代码如下:

#pragma once
#include<vector>
#include<list>
namespace zp
{
	template<class T, class Container>
	class stack
	{
	public:
		void push(const T& x)
		{
			_vv.push_back(x);
		}


		void pop()
		{
			if (!_vv.empty())
			{
				_vv.pop_back();
			}
		}

		const T& top()
		{
			return _vv.back();
		}


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


		size_t size()
		{
			return _vv.size();
		}

	private:
		Container _vv;
	};
}
  • 当我们要实现数组栈、链式栈,我们还需要自己实现吗,在这里就可以使用适配器模式,使用已有的容器对其进行封装操作;
  • 但是当我们像 vector<T> _vv list<int> _vv  样定义时其实还没有真正的实现适配。就像平常生活中的电源适配器一样的,它可以把220v的转化为 10v 或者 20v ,因此在定义模板增加了一个【Container】的模板参数,即  ⚔️ template<class T, class Container> ⚔️ ,当然当我们想实现数组栈还可以这样  ⚔️ template<class T, class Container = vector<T>> ⚔️

当我们想使用时直接用即可:

stack<int, vector<int>> str;
stack<int, list<int>> str;
stack<int> str;


(四)题目讲解

1、逆波兰表达式求值

  • 链接如下:150. 逆波兰表达式求值

 题目如下:

t

 解题思路:

首先,在正式的解题之前,我们先认识一下什么叫做逆波兰表达式。

 💨 逆波兰表达式是一种计算表达式的方式,也称为后缀表达式

  • 它的特点是把操作符写在操作数的后面,从左到右扫描表达式,遇到操作数就把它压入栈中,遇到操作符就从栈中取出所需的操作数进行运算,运算结果再存入栈中;
  • 最后栈中只剩下一个数,即该表达式的计算结果。

首先,我先举例分析一波例如,表达式tokens = ["2","1","+","3","*"] 的运算过程如下:

  1. 扫描到数字2,将其压入栈中。
  2. 扫描到数字1,将其压入栈中。
  3. 扫描到符号"+",从栈中弹出操作数4和3,计算2+1=3,将结果3压入栈中。
  4. 继续扫描,将数字3压入栈中。
  5. 扫描到符号" * ",从栈中弹出操作数3和3,计算3*3=9,将结果9压入栈中。
  6. 表达式扫描完毕,栈中剩下唯一数字9,即该表达式的计算结果。

因此以下是逆波兰表达式的解题思路:

  1. 定义一个栈s,用于存放操作数和中间运算结果。

  2. 从左到右扫描表达式,遇到数字就把它压入栈中。

  3. 遇到操作符时,从栈中弹出两个操作数进行运算。运算结果再压入栈中。

  4. 重复步骤2和3,直到表达式扫描完毕。

  5. 栈中剩下的唯一数字就是该表达式的计算结果。

代码展示:

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> s;
        for (auto e : tokens) {
            if (e == "+" || e == "-" || e == "*" || e == "/") {
                int b = s.top();
                s.pop();
                int tmp = s.top();
                s.pop();
                if (e == "+") 
                    s.push(tmp + b);
                else if (e == "-") 
                    s.push(tmp - b);
                else if (e == "*") 
                    s.push(tmp * b);
                else if (e == "/") 
                    s.push(tmp / b);
            } 
            else {
                s.push(stoi(e));
            }
        }
    return s.top();
    }
};


(五)总结

到此,关于本期stack的讲解便到此结束了。接下来,总结一下本期都学到了什么吧!!!

  • 1、首先,我们通过文档的介绍了解了有关STL库关于stack的基本介绍,知道了在库中是一个模板类,其次给大吉介绍了有关容器适配器的基本知识;
  • 2、接下来,我们简单的使用了一下stack,知道了用法;
  • 3、紧接着,我们手动的去实现了一个stack,相比之前的stack的实现就显得十分简单了;
  • 4、最后,有了基本概念,在带着大家刷了几道题以巩固学到的关于stack的知识。

以上便是本文的基本内容,感谢大家的阅读与支持!!!

 

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

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

相关文章

Flutter 笔记 | Flutter 功能性组件

拦截返回键&#xff08;WillPopScope&#xff09; 为了避免用户误触返回按钮而导致 App 退出&#xff0c;在很多 App 中都拦截了用户点击返回键的按钮&#xff0c;然后进行一些防误触判断&#xff0c;比如当用户在某一个时间段内点击两次时&#xff0c;才会认为用户是要退出&a…

docker 服务环境搭建(mysql、rabbitmq、redis、nginx、springboot)

一般来说一个项目&#xff0c;百分之80都会用到以上这些&#xff0c;尤其是产品初期的demo 这些我都写过博客&#xff0c;但是我每次要去安装&#xff0c;都要去我不同的博客里面翻找&#xff0c;很烦&#xff0c;把他们聚在一起&#xff0c;方便我以后cv&#xff0c;就是这篇博…

注意力Transformer

注意力 注意力分为两步&#xff1a; 计算注意力分布 α \alpha α 其实就是&#xff0c;打分函数进行打分&#xff0c;然后softmax进行归一化 根据 α \alpha α来计算输入信息的加权平均&#xff08;软注意力&#xff09; 其选择的信息是所有输入向量在注意力下的分布 打…

基于中序有序的二叉搜索树

文章目录 什么是二叉搜索树二叉搜索树的中序遍历二叉搜索树的查找查找的非递归写法查找的递归写法 二叉搜索树的插入非递归递归 二叉搜索树的删除非递归递归 二叉搜索树的使用场景k模型kv模型 什么是二叉搜索树 二叉搜索树是普通二叉树的升级&#xff0c;普通二叉树除了存储数…

3、js - 垃圾回收机制

1、基础概念 &#xff08;1&#xff09;js内存的生命周期 -1- 内存分配&#xff1a;当声明变量、函数、对象时&#xff0c;系统会自动分配内存给它们 -2- 内存使用&#xff1a;即读写内存&#xff0c;也就是使用变量、函数 -3- 内存回收&#xff1a;使用完毕&#xff0c;由垃圾…

时间跟踪工具:Timemator Mac汉化版

Timemator是一款Mac平台上的时间跟踪工具&#xff0c;它可以帮助用户记录和分析日常工作和任务所花费的时间。Timemator提供了多种时间跟踪功能&#xff0c;包括自动跟踪应用程序和文档、手动添加时间记录、设置定时器等&#xff0c;让用户可以轻松记录和管理时间。 活动时间表…

互联网及SaaS行业如何落地体验管理?

3月25日&#xff0c;「体验家XMPlus」携手PMTalk成功举办了以“2023用户体验新趋势与数据增长实践”为主题的线下沙龙。 在本次活动中&#xff0c;有100多位来自不同企业的产品经理前来参与&#xff0c;大家聚集一起互相交流、分享经验。“体验家”的产品总监李若晨先生也进行了…

[RSA议题分析] Aikido Turning EDRs to malicious wipers using 0-day exploits

文章目录 简介议题分析wiperEDRWindows of Opportunity 总结 简介 本篇议题是由SafeBreach实验室的Or Yair带来的&#xff0c;主要通过利用EDR的删除恶意软件的能力和windows软连接与延迟删除文件的能力去制造一个可以在普通户权限下删除任意文件的恶意软件 - Aikido。这本质上…

科技云报道:汽车云,云计算换挡后的下一个“赛点”?

科技云报道原创。 从去年开始&#xff0c;汽车云似乎成为了云计算赛道的“香饽饽”。 尤其是在下半年&#xff0c;无论是阿里、腾讯、华为三大云巨头&#xff0c;还是百度云、京东云、字节云等奋力争夺“第四朵云”的玩家&#xff0c;均已各种形式“刷新”了其汽车云战略。玩…

Revit中窗族的立面出图设置和构件显隐

​  一、窗族的立面出图设置 Revit中&#xff0c;除了平面的出图设置以外还有立面的出图设置。 例如&#xff1a;如何在立面中&#xff0c;使窗户在精细详细程度显示的是窗的全部主体结构而在粗略/中等详细程度下是显示这样的样式呢? 在窗族样板中&#xff0c;打开立面&…

unity uitoolkit学习

使用UI Toolkit Debugger查看元素 1、打开面板 2、找到元素 在UI Builder窗体&#xff0c;别忘了打开Preview再选择元素 3、可以选择不同类型的窗体 4、查看元素的样式 需要注意的是下面的样式会覆盖上面的 5、调试 修改内置控件样式 1、找到PanelSettings>Theme St…

如果STM32/GD32一类的ARM单片机解除读写保护的方法

文章目录 前言一、打开软件二、连接到目标芯片1.连接2.若目标芯片无写包含3. 若存在读写保护 三、解除读写保护的操作&#xff1a;1. 打开Options Bytes对话框2. 操作步骤 四、工具下载链接 前言 有时候啊&#xff0c;使用ST-Link给STM32一类的ARM单片机下载程序的时候&#x…

Fastjson过滤器用法

fastjson git地址&#xff1a;https://github.com/alibaba/fastjson/wiki SimplePropertyPreFilter 用法 用于过滤某个属性 SimplePropertyPreFilter filter new SimplePropertyPreFilter();filter.getExcludes().add("gender");A a new A(1,"zhangsan"…

CSS样式的三种引入方式及优先级

说明&#xff1a;网页开发有三种技术&#xff0c;分别是html、css和js&#xff0c;分别对应页面的结构、表现和动作。css样式引入&#xff0c;是指把对页面的渲染作用到html上&#xff0c;有以下三种方式&#xff1a;行内式、内嵌式和外联式。 第一种&#xff1a;行内式&#…

噶了呀,现在的00后这么卷的吗?

现在的小年轻真的卷得过分了。前段时间我们公司来了个00年的&#xff0c;工作没两年&#xff0c;跳槽到我们公司起薪20K&#xff0c;都快接近我了。 后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了。 最近和他聊了一次天&#xff0c;原来这位小老弟家里…

KDZD自动脱扣型绝缘靴(手套)耐压试验装置支架

一、概述 KDZD自动脱扣型绝缘靴&#xff08;手套&#xff09;耐压试验装置支架是根据《DLT 976-2017 带电作业工具、装置和设备预防性试验规程》、《DLT 1476-2015电力安全工器具预防性试验规程》、《GBT 17622-2008带电作业用绝缘手套》、《CB21148 2020足部防护 安全鞋》等相…

VBA学习-循环语句

目录 一、基础知识学习 二、单元格格式 三、循环语句与判断语句 一、基础知识学习 1、对单元格赋值 Sub 赋值()对单元格进行赋值Range("A1").Value 100End Sub 2、多区域赋值 Sub 多个区域赋值() 多区域赋值Range("B1:C2").Value 200 End Sub 3、不…

2023年10月自考本科如何报名,报考流程是怎样的?

自考本科报名条件&#xff1a; 自考本科没有条件与要求&#xff0c;国家规定&#xff1a;凡中华人民共和国公民&#xff0c;不受性别、年龄、民族、种族和已受教育程度的限制&#xff0c;均可参加自学考试。但是&#xff0c;需要注意的是&#xff0c;办理本科毕业证书者&#x…

2023年,真的别裸辞....

作为IT行业的大热岗位——软件测试&#xff0c;只要你付出了&#xff0c;就会有回报。说它作为IT热门岗位之一是完全不虚的。可能很多人回说软件测试是吃青春饭的&#xff0c;但放眼望去&#xff0c;哪个工作不是这样的呢&#xff1f;会有哪家公司愿意养一些闲人呢&#xff1f;…

【TellMeCode】使用VSCODE + ChatGPT辅助分析推测源码

【TellMeCode】使用VSCODE ChatGPT辅助分析推测源码 0x00 功能简介 根据代码上下文相关信息&#xff0c;如工作区文件夹名称&#xff0c;代码所在路径等一系列信息&#xff0c;提供给大模型更多元和尽可能多的信息&#xff0c;利用其自身优势去检索相关的文档和博客&#xf…