【C++初阶】stack的常见操作和模拟实现

news/2024/10/25 19:25:57/

在这里插入图片描述

👦个人主页:@Weraphael
✍🏻作者简介:目前学习C++和算法
✈️专栏:C++航路
🐋 希望大家多多支持,咱一起进步!😁
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注✨


目录

  • 一、stack
    • 1.1 stack的基本概念
    • 1.2 stack的常见操作
      • 1.2.1 常见构造函数
      • 1.2.2 push
      • 1.2.3 pop
      • 1.2.4 empty
      • 1.2.5 top
      • 1.2.6 size
      • 1.2.7 栈的遍历
  • 二、有关栈的力扣经典题
    • 2.1 最小栈
    • 2.2 栈的压入、弹出序列
    • 2.3 逆波兰表达式求值
    • 2.4 用栈实现队列
  • 三、模拟实现stack
    • 3.1 简介
    • 3.2 代码实现

一、stack

1.1 stack的基本概念

在这里插入图片描述

  • stack是一种容器适配器(通过容器转化出来的),是一种先进后出(First in Last Out,简称FILO),它只有一个出口。
  • 容器适配器是一种特殊的容器,它们通过某种方式改变了底层容器的接口或行为。常见的容器适配器还有队列queue和优先队列priority_queue
  • 注意:容器适配器通常会限制对底层容器的访问方式,只有栈顶的元素才能被使用,因此不能有遍历的行为(底层没有设计迭代器)。例如栈和队列都是限制在一端插入或删除元素,优先队列则通过堆来维护元素的有序性。

在这里插入图片描述

1.2 stack的常见操作

在这里插入图片描述

1.2.1 常见构造函数

  • 无参的默认构造(构造空的栈)
// T可以是任意类型
stack<T> _st;
  • 拷贝构造
// _st已知
stack<T> _st(s);

1.2.2 push

功能:将元素val压入stack

1.2.3 pop

功能:stack中尾部的元素弹出

1.2.4 empty

功能:判断stack是否为空,如果为空则返回真,反之。

1.2.5 top

功能:返回栈顶元素

1.2.6 size

功能:返回stack中元素的个数

在这里插入图片描述

1.2.7 栈的遍历

既然栈不支持迭代器,只能打印栈顶的元素,然后出栈。重复以上操作直到栈为空

【代码示例】

#include <iostream>
#include <stack>
using namespace std;int main()
{stack<int> _st;_st.push(1);_st.push(2);_st.push(3);_st.push(4);while (!_st.empty()){cout << _st.top() << ' ';_st.pop();}cout << endl;return 0;
}

【输出结果】

在这里插入图片描述

二、有关栈的力扣经典题

2.1 最小栈

题目链接:点击跳转

【题目描述】

在这里插入图片描述

【思路】

可以定义两个栈,一个栈_st可以用于出栈和入栈操作,另一个栈_min_st用于更新当前_st出栈和入栈的最小值。

对于入栈接口:_st正常入栈。如果_min_st为空,则入栈的值val_st一样;如果不为空,则要比较_min_st当前栈顶的元素是否大于或者等于_st的栈顶元素,如果大于或等于则要入栈。

对于出栈接口:首先要分析_st的栈顶元素是否等于_min_st的栈顶元素,如果相等则要出栈,而_st无论如何都要出栈。

最后,_min_st的栈顶元素则是最小元素的栈。

在这里插入图片描述

【代码实现】

class MinStack {
public:MinStack() {}// 自定义类型会调用默认构造函数// 因此可以不用写void push(int val) {_st.push(val);if (min_st.empty() || val <= min_st.top()){min_st.push(val);}}void pop() {if (_st.top() == min_st.top()){min_st.pop();}_st.pop();}int top() {return _st.top();}int getMin() {return min_st.top();}private:stack<int> _st; stack<int> min_st;
};

2.2 栈的压入、弹出序列

题目链接:点击跳转

【题目描述】

在这里插入图片描述

【思路】

这题直接模拟就行了。

首先定义一个栈_st,并且分别定义变量ij来遍历pushV数组和popV数组,接下来让pushV里的元素一个一个入栈(i++),然后再判定栈顶元素是否等于popV下标为j的元素,如果相等则要出栈。最后如果栈为空,说明栈popV是是pushV弹出的顺序。

要注意pushV可能为空

【代码实现】

class Solution {
public:bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {stack<int> _st;int i = 0; // 遍历pushVint j = 0; // 遍历popVwhile (i < pushV.size()){// 入栈_st.push(pushV[i]);i++;while (!_st.empty() && _st.top() == popV[j]){_st.pop();j++;}}// 如果栈为空,说明匹配return _st.empty();}
};

2.3 逆波兰表达式求值

题目链接:点击跳转

【题目描述】

在这里插入图片描述

【思路】

首先来解释什么是逆波兰表达式求值,逆波兰表达式求值又称后缀表达式,而我们常见的是中缀表达式,例如2 + 1 * 3化成后缀表达式2 1 3 * +

因此我们的思路是:
设计一个栈_st,如果遇到操作数,则将操作数入栈;如果遇到运算符(本题的操作符只有+ - * /),则将两个操作数出栈,但是要注意操作数的顺序,先出栈的是右操作数,出栈后的下一个栈顶元素则是左操作数,对于加法和乘法来说操作数的顺序是无关紧要的,但是对于减法和除法,操作数就要有讲究了。

最后计算出的值继续入栈,直到遍历完毕之后,栈内只有一个元素,则该元素(也就是栈顶)为逆波兰表达式的值。

注意要将string类字符串转化成整型计算,string转化成整型有个函数:atoi

【代码实现】

class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> _st;for (auto& x : tokens){if (x != "+" && x != "-" && x != "*" && x != "/"){// 如果不为操作符就入栈_st.push(stoi(x));}else{int right = _st.top();_st.pop();int left = _st.top();_st.pop();// 计算switch(x[0]){case '+':_st.push(left + right);break;case '-':_st.push(left - right);break;case '*':_st.push(left * right);break;case '/':_st.push(left / right);break;}}}return _st.top();}
};

2.4 用栈实现队列

题目链接:点击跳转

【题目描述】

在这里插入图片描述

【思路】

举一组数据:1、2、3、4。如果是出栈的话,第一个出的数据是4,而现在要用栈来模拟队列,第一个出的数据必须是1。所以一开先将4个数据全部入栈(push),然后一个个出栈到另一个栈(pop)中,这样1就在栈顶了,对于栈的性质,靠近栈顶的元素先出,这样就能实现栈模拟队列了。

【动图展示】

在这里插入图片描述

【代码实现】

class MyQueue {
public:MyQueue() {}void push(int x) {_st.push(x);}int pop() {if (_queue.empty()){while (!_st.empty()){int val = _st.top();_st.pop();_queue.push(val);}}int front_val = _queue.top();_queue.pop();return front_val;}int peek() {if (_queue.empty()){while (!_st.empty()){int val = _st.top();_st.pop();_queue.push(val);}}return _queue.top();}bool empty() {return _queue.empty() && _st.empty();}private:stack<int> _st;stack<int> _queue;
};

三、模拟实现stack

3.1 简介

在这里插入图片描述

stack是一种容器适配器,容器适配器可以被视为一种包装器,它们通过修改底层容器的接口或行为来实现新的功能。通过使用这些容器适配器,开发者可以方便地在不同场景下使用已有容器的功能,并且无需关心底层容器的具体实现。

其实就是STL中封装好的栈,在使用的时候我们不仅可以指定内部的数据类型,还可以指定内部的容器。不指定容器其实也是可以的,模板参数有一个缺省值,默认是deque

int main()
{//内部容器为vectorstack<int, vector<int>> s1;  //内部容器为list   stack<int, list<int>> s2; //内部为默认容器deque      stack<int> s3;      return 0;
}

3.2 代码实现

注意:指定内部的容器需要有push_backpop_backbacksizeempty等函数接口

#pragma oncenamespace wj
{template<class T, class container = deque<T>>class stack{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}T& top(){return _con.back();}size_t size(){return _con.size();}bool empty(){return _con.empty();}private:container _con;};
}

【测试代码】

#include <iostream>
#include <deque>
using namespace std;
#include "stack.h"
int main()
{wj::stack<int> _st;_st.push(1);_st.push(2);_st.push(3);_st.push(4);while (!_st.empty()){cout << _st.top() << ' ';_st.pop();}cout << endl;cout << "个数为:" << _st.size() << endl;return 0;
}

【输出结果】

在这里插入图片描述


http://www.ppmy.cn/news/1075974.html

相关文章

Python2022年09月Python二级 -- 编程题解析

第一题: 某航空公司对于托运行李有尺寸要求&#xff0c;必须满足以下条件:每件托运行李的长、宽、高三边之和须大于或等于60厘米&#xff0c;且小于或等于203厘米。(注意只是三边&#xff0c;不考虑立方体的整个周长&#xff0c;相当于只求长宽高三个数字的和&#xff0c;如&am…

大数据学习06-Spark分布式集群部署

Spark完全分布式部署 前期准备&#xff0c;每台服务器都需要配置安装Scala下载Scala安装包配置环境变量 安装spark解压配置环境修改配置 前期准备&#xff0c;每台服务器都需要配置 配置好IP vim /etc/sysconfig/network-scripts/ifcfg-ens33 TYPE"Ethernet" PROX…

linux————pxe网络批量装机

目录 一、概述 什么是pxe pxe组件 二、搭建交互式pxe装机 一、配置基础环境 二、配置vsftpd 三、配置tftp 四、准备pxelinx.0文件、引导文件、内核文件 一、准备pxelinux.0 二、准备引导文件、内核文件 五、配置dhcp 一、安装dhcp 二、配置dhcp 六、创建default文…

Python中30个常见的内置函数使用讲解(一)

摘要&#xff1a; Python作为一种强大的编程语言&#xff0c;提供了丰富的内置函数&#xff0c;用于各种常见操作&#xff0c;如数学运算、数据转换、迭代控制等。本文将从入门到精通&#xff0c;详细介绍Python中常见的内置函数的用法&#xff0c;通过代码示例和中文注释&…

大门设得好,财旺运也旺

大门作为我们家庭里一扇保护家人的屏障&#xff0c;可以说是非常重要的&#xff0c;它不仅能起到安全作用&#xff0c;在风水上也是非常关键的。大门在风水中是财运进气的门道&#xff0c;大门风水的好坏直接影响到房屋的整体风水&#xff0c;好的大门风水可以让主人旺财又旺运…

国标GB28181视频监控EasyGBS国标视频平台分享链接不生效的问题解决方案

EasyGBS平台可提供流媒体接入、处理、转发等服务&#xff0c;支持内网、公网的监控设备通过国标GB/T28181协议进行视频监控直播。平台可拓展性强&#xff0c;部署灵活&#xff0c;可实现的视频能力有&#xff1a;实时直播、视频录像、语音对讲、云存储、检索及回放、告警、级联…

【重要】【转载】NOR Flash芯片内执行(XIP)

为什么程序不能直接在nandflash上执行&#xff1f;出于这个疑惑带来了这篇博文&#xff0c;是我在网上找了很多资料后总结的&#xff0c;假如有误&#xff0c;希望马上指出来&#xff0c;免得我误人子弟。谢谢&#xff01; 首先认识下nandflash和norflash&#xff1a; NOR Flas…

AMEYA360:ROHM开发出适用于条码标签打印应用、超快打印速度的热敏打印头

AMEYA360&#xff1a;ROHM开发出适用于条码标签打印应用、超快打印速度的热敏打印头 全球知名半导体制造商ROHM(总部位于日本京都市)新推出两款高可靠性高速热敏打印头 “TE2004-QP1W00A(203dpi)”和“TE3004-TP1W00A(300dpi)”&#xff0c;新产品非常适用于物流和库存管理等领…