数据结构——栈的应用

数据结构——栈的应用

  • 括号匹配
  • 中缀转后缀
    • 什么是中缀后缀
      • 中缀表达式 (Infix Notation)
      • 后缀表达式 (Postfix Notation, Reverse Polish Notation, RPN)
    • 加减,乘除运算
    • 处理括号
    • 后缀转中缀

我们今天来看栈的应用:

括号匹配

栈一个经典的应用就是括号匹配:

https://leetcode.cn/problems/valid-parentheses/description/

在这里插入图片描述
在这里插入图片描述
我们遇到的字符串可能更复杂,比如像:([{{{()]]{}(}}}{}

首先我们知道的,一个左括号如果要匹配,必须要有对应的右括号,而且是匹配最近的,而且最里面的左括号优先匹配对应的右括号(从最里面开始匹配,方便我们的检测,如果从最外面开始,会比较费劲)
在这里插入图片描述
所以我们思想是这样的:

1.凡是遇到左括号就入栈
2. 一旦遇到右括号,就弹出进行对应匹配,如果匹配,则弹出,否则返回无效
3. 最后,扫描完并且栈为空,说明这是合法的括号字符串

class Solution {
public:bool isValid(string s) {//判断字符串的长度int lenghth = s.size();if(lenghth % 2 != 0)return false;stack<char> st;//左括号入栈for(int i = 0; i < lenghth ; i++){if(s[i] == '(' || s[i] == '{' || s[i] == '['){st.push(s[i]);}else{if(st.empty()) return false;if (s[i] == ')' && st.top() != '(') return false;if (s[i] == '}' && st.top() != '{') return false;if (s[i] == ']' && st.top() != '[') return false;st.pop();}}return st.empty();}
};

如果学习过unordered_map还可以这样玩:

class Solution {
public:bool isValid(string s) {int lenghth = s.size();if(lenghth % 2 != 0)return false;unordered_map<char, char> pairs = {{')', '('},{']', '['},{'}', '{'}  //形成键值对关系};stack<char> st;for(auto ch : s){if(pairs.count(ch)){if(st.empty() || st.top() != pairs[ch]){return false;}st.pop();}else{st.push(ch);}}return st.empty();   }};

中缀转后缀

什么是中缀后缀

中缀表达式和后缀表达式是两种不同的数学表达式表示方法,它们在结构和计算方式上有所区别。下面分别对这两种表达式进行详细解释:

中缀表达式 (Infix Notation)

定义
中缀表达式是我们日常生活中最常用的数学表达式书写形式,其中运算符位于其作用的两个操作数之间。这种表达方式之所以被称为“中缀”,是因为运算符处于操作数的中间位置。

示例

3 + 4 * 5
(10 / 2) - 3

在这两个例子中,“+”、“*”、“/”和“-”分别是中缀运算符,它们位于相关操作数之间。

特点

  • 符合人类自然阅读和书写的习惯,直观易懂。
  • 计算中缀表达式时需要遵循特定的运算顺序规则,如先乘除后加减、同级运算符从左到右等,以及括号来改变默认优先级。
  • 由于依赖运算符优先级和结合性,计算机在处理中缀表达式时通常需要额外的解析步骤来确定正确的计算顺序。

后缀表达式 (Postfix Notation, Reverse Polish Notation, RPN)

定义
后缀表达式(又称为逆波兰表示法)是一种运算符置于其作用的操作数之后的表达式形式。在这种表示法中,不再需要括号来明确运算顺序,因为每个运算符都是在其所需的所有操作数已经出现之后才出现的。

示例

3 4 5 * +
10 2 / 3 -

这里,“*”、“+”、“/”和“-”同样是运算符,但它们现在出现在各自操作数之后。

特点

  • 后缀表达式消除了对括号的需求,因为其结构已经明确指定了运算顺序:从左到右扫描表达式,遇到数字时直接压入堆栈,遇到运算符时弹出堆栈中足够的操作数进行计算,并将结果压回堆栈。
  • 计算机可以直接按照从左到右的顺序遍历来计算后缀表达式,无需复杂的优先级判断,因此非常适合机器处理,尤其是在需要高效计算的场合。
  • 对于人类阅读者来说,后缀表达式不如中缀表达式直观,但其计算逻辑简洁且易于编程实现。

转换与计算
将中缀表达式转换为后缀表达式通常涉及使用栈数据结构来处理运算符的优先级和结合性。转换完成后,后缀表达式可以直接通过一个简单的栈机制进行计算,无需复杂的解析过程。

总结来说,中缀表达式是人们习惯的数学书写方式,直观易读但计算时需考虑运算符优先级;而后缀表达式虽然对人不太直观,但其结构清晰、计算简单,特别适用于计算机自动化处理。

现在给你一个中缀表达式要求你转成后缀表达式:

https://www.nowcoder.com/practice/4e7267b55fdf430d9403aa12206572b3?tpId=182&tqId=34663&ru=/exam/oj

在这里插入图片描述
我们先从简单的开始:
在这里插入图片描述

加减,乘除运算

加减,乘除运算,乘除运算是比加减运算级高的,所以我们在入栈的时候,要考虑运算符的优先顺序:
在这里插入图片描述
还是和之前一样,如果为操作数,直接打印:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个时候,- 号的优先级和+号一样,说明在此时+可以完成了动作,所以出栈:
在这里插入图片描述
之后继续向后走:
在这里插入图片描述

这个时候遇到了乘号,比栈顶元素的优先级高,先入栈
在这里插入图片描述

当前操作符的优先级高于栈顶运算符时,表明栈顶运算符应当在其之后完成计算。因此,为了保持正确的运算顺序,应该先将当前高优先级运算符压入栈中,待将来可能遇到的更低优先级运算符(或者遇到栈顶运算符的右括号对)时再将其弹出。这样确保了高优先级运算符始终晚于低优先级运算符出栈,符合后缀表达式的构建规则。

之后重复上面的步骤,我们就可以得到完整的后缀表达式。总结一下:

  1. 初始化一个空的栈stk,用于存储操作符和左括号。
  2. 从左到右扫描中缀表达式的每个字符。
  • 遇到操作数,将其添加到输出字符串中。
  • 遇到操作符(+、-、*、/),则将其与栈stk顶的操作符进行优先级比较:
    a. 如果栈stk为空,则将操作符压入栈stk。
    b. 如果操作符的优先级高于栈顶操作符,则将操作符压入栈stk。
    c. 如果操作符的优先级小于等于栈顶操作符,则将栈顶操作符弹出并添加到输出字符串中,然后重复步骤4。
    当扫描完中缀表达式后,将栈stk中剩余的操作符依次弹出并添加到输出字符串中。
#include<iostream>
#include<string>
#include<stack>
#include <cctype>
#include<unordered_map>using namespace std;// 定义一个无序映射(哈希表),用于存储运算符及其优先级
unordered_map<char, int> pairs = {{'+', 1}, // 加法优先级为1{'-', 1}, // 减法优先级为1{'*', 2}, // 乘法优先级为2{'/', 2}  // 除法优先级为2
};// 函数声明:将输入的中缀表达式字符串转换为后缀表达式字符串
string infixToPostfix(const string &infix)
{// 定义一个字符栈stk用于存储运算符stack<char> stk;// 初始化后缀表达式字符串postfixstring postfix;// 遍历输入的中缀表达式字符串中的每个字符for (char ch : infix){// 如果字符为字母或数字(即操作数),直接添加到后缀表达式字符串中if (isalnum(ch)){postfix += ch;}// 否则,假设当前字符为运算符else{// 当栈非空,且当前运算符优先级小于等于栈顶运算符优先级时while (!stk.empty() && pairs[ch] <= pairs[stk.top()]){// 将栈顶运算符弹出并添加到后缀表达式字符串中postfix += stk.top();stk.pop();}// 将当前运算符压入栈中stk.push(ch);}}// 当栈非空时,依次弹出栈顶运算符并添加到后缀表达式字符串中while (!stk.empty()){postfix += stk.top();stk.pop();}// 返回生成的后缀表达式字符串return postfix;
}int main()
{// 定义并初始化中缀表达式字符串infixstring infix;cout << "请输入中缀表达式: ";cin >> infix;// 调用infixToPostfix函数将输入的中缀表达式转换为后缀表达式,并存储在postfix变量中string postfix = infixToPostfix(infix);// 输出转换后的后缀表达式cout << "后缀表达式为: "<< postfix<< endl;// 程序结束,返回0return 0;
}

在这里插入图片描述
在这里插入图片描述

处理括号

如果出现括号,我们可以理解为:括号可以提升优先等级,所以左括号直接入栈,直到遇到右括号,再依次弹出,直到把左括号也弹出栈

#include<iostream>
#include<string>
#include<stack>
#include <cctype>
#include<unordered_map>using namespace std;// 定义一个无序映射(哈希表),用于存储运算符及其优先级
unordered_map<char, int> pairs = {{'+', 1}, // 加法优先级为1{'-', 1}, // 减法优先级为1{'*', 2}, // 乘法优先级为2{'/', 2}  // 除法优先级为2
};// 函数声明:将输入的中缀表达式字符串转换为后缀表达式字符串
string infixToPostfix(const string &infix)
{// 定义一个字符栈stk用于存储运算符和括号stack<char> stk;// 初始化后缀表达式字符串postfixstring postfix;// 遍历输入的中缀表达式字符串中的每个字符for (char ch : infix){// 如果字符为字母或数字(即操作数),直接添加到后缀表达式字符串中if (isalnum(ch)){postfix += ch;}// 处理左括号:直接压入栈中else if (ch == '('){stk.push(ch);}// 处理右括号:else if (ch == ')'){// 当栈非空,且栈顶元素不是左括号时,不断弹出栈顶元素并添加到后缀表达式字符串中while (!stk.empty() && stk.top() != '('){postfix += stk.top();stk.pop();}// 弹出匹配的左括号(不添加到后缀表达式字符串)stk.pop();}// 处理其他运算符(非括号):else{// 当栈非空,且当前运算符优先级小于等于栈顶运算符优先级时while (!stk.empty() && pairs[ch] <= pairs[stk.top()]){// 将栈顶运算符弹出并添加到后缀表达式字符串中postfix += stk.top();stk.pop();}// 将当前运算符压入栈中stk.push(ch);}}// 当栈非空时,依次弹出栈顶元素并添加到后缀表达式字符串中(此时栈中仅剩运算符)while (!stk.empty()){postfix += stk.top();stk.pop();}// 返回生成的后缀表达式字符串return postfix;
}int main()
{// 定义并初始化中缀表达式字符串infixstring infix;cout << "请输入中缀表达式: ";cin >> infix;// 调用infixToPostfix函数将输入的中缀表达式转换为后缀表达式,并存储在postfix变量中string postfix = infixToPostfix(infix);// 输出转换后的后缀表达式cout << "后缀表达式为: "<< postfix<< endl;// 程序结束,返回0return 0;
}

在这里插入图片描述

后缀转中缀

后缀转中缀思路就是逆着上面的思路,力扣上面有一道类似的题:

https://leetcode.cn/problems/8Zf90G/description/

在这里插入图片描述

力扣上面有比较全面的解析,这里不再赘述,大家可以去看官方解答:

class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> stk;int n = tokens.size();for (int i = 0; i < n; i++) {string& token = tokens[i];if (isNumber(token)) {stk.push(atoi(token.c_str()));} else {int num2 = stk.top();stk.pop();int num1 = stk.top();stk.pop();switch (token[0]) {case '+':stk.push(num1 + num2);break;case '-':stk.push(num1 - num2);break;case '*':stk.push(num1 * num2);break;case '/':stk.push(num1 / num2);break;}}}return stk.top();}bool isNumber(string& token) {return !(token == "+" || token == "-" || token == "*" || token == "/");}
};

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

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

相关文章

set_input_delay的理解

1&#xff0c;set_input_delay约束理解 input_delay是指输入的数据到达FPGA的pad引脚时相对于时钟边沿的延迟有多大&#xff0c;单位是ns&#xff0c;数值可以是正&#xff0c;也可以是负。通过set_input_delay约束告诉编译器输入时钟和输入数据的相位关系。如下图所示假设时钟…

数字IC后端先进工艺设计实现之TSMC 12nm 6Track工艺数字IC后端实现重点难点盘点

大家知道咱们社区近期TSMC 12nm ARM Cortexa-A72(1P9M 6Track Metal Stack)已经开班。这里小编要强调一点:不要认为跑了先进工艺的项目就会很有竞争力&#xff01;如果你仅仅是跑个先进工艺的flow&#xff0c;不懂先进工艺在数字IC后端实现上的不同点&#xff0c;为何有这样的不…

推荐一个wordpress免费模板下载

首页大背景图&#xff0c;首屏2张轮播图&#xff0c;轮换展示&#xff0c;效果非常的炫酷&#xff0c;非常的哇噻&#xff0c;使用这个主题搭建的wordpress网站&#xff0c;超过了200个&#xff0c;虽然是一个老主题了&#xff0c;不过是经得起时间考验的&#xff0c;现在用起来…

[iOS]使用CocoaPods发布公开库

1.检查库名是否已被占用 选择库名时&#xff0c;尽量选择具有描述性并且独特的名字&#xff0c;这不仅可以避免命名冲突&#xff0c;还可以帮助用户更好地理解库的用途和功能。 在实际创建和发布 CocoaPods 库之前&#xff0c;确实应该检查库名是否已经被占用&#xff0c;以避…

敏捷之Scrum开发

目录 一、什么是 Scrum 1.1 Scrum 的定义 二、Scrum 迭代开发过程 2.1 迭代开发过程说明 2.1.1 开发方法 2.1.1.1 增量模型 2.1.1.1.1 定义 2.1.1.1.2 模型方法说明 2.1.1.2 迭代模型 2.1.1.2.1 定义 2.1.1.2.2 模型方法说明 2.1.2 迭代过程 2.1.2.1 产品需求Produ…

万万没想到,原来这些维生素对帕金森有好处!

亲爱的读者朋友们&#xff0c;今天我们要聊一个特别的群体——帕金森病患者。在面对这一神经系统退行性疾病时&#xff0c;除了遵循医嘱进行药物治疗和康复锻炼&#xff0c;合理的饮食和营养补充也显得尤为重要。那么&#xff0c;究竟哪些维生素是他们不可或缺的呢&#xff1f;…

go语言实现简单登陆返回token样例

目录 1、代码实现样例&#xff1a; 2、postman调用&#xff0c;获取登陆后的token&#xff1a; 1、代码实现样例&#xff1a; package mainimport ("net/http""time""github.com/dgrijalva/jwt-go""github.com/gin-gonic/gin" )var …

【代码问题】【Pytorch】训练模型时Loss为NaN或INF

解决方法或者问题排查&#xff1a; 加归一化层&#xff1a; 我的问题是我新增的一个模块与原来的模块得到的张量相加&#xff0c;原张量是归一化后的&#xff0c;我的没有&#xff1a; class Module(nn.Module):def __init__(self,dim,):super().__init__()# 新增一个LayerNo…

python学习笔记B-13:序列结构之元组--元组的相关操作

元组的常用相关操作有&#xff1a;获取最大值、获取最小值、获取元组长度、查询是否包好某元素、获取元素索引值、获取元素数量 t (2,4,6,90,34,25,78) print("原元组&#xff1a;",t) print("最大值&#xff1a;",max(t)) print("最小值&#xff1…

matlab新手快速上手3(差分进化算法)

本文用经典差分进化框架模板&#xff0c;对matlab新手友好&#xff0c;快速上手看懂matlab代码&#xff0c;快速应用实践&#xff0c;源代码在文末给出。 差分进化算法定义&#xff1a; 差分进化算法&#xff08;Differential Evolution&#xff0c;简称DE算法&#xff09;是…

KUKA机器人如何给IO信号或寄存器添加中文注释信息?

KUKA机器人如何给IO信号或寄存器添加中文注释信息? 如下图所示,首先,我们需要登录专家以上用户权限(默认密码KUKA), 如下图所示,点击“投入运行”—“网络配置”, 如下图所示,此时机器人的IP地址为192.168.1.10, 如下图所示,用一根网线连接机器人控制柜到笔记…

基于SpringBoot+Vue大学生兼职管理系统的设计与实现

目录 一、前言介绍 二、功能需求 三、功能结构设计 四、管理员功能实现 招聘单位管理 用户管理 论坛管理 公告信息管理 五、招聘单位功能实现 职位招聘管理 职位留言管理 简历投递管理 六、用户功能实现 在线论坛 职位招聘信息 简历投递 简历 七、部分核心代码 …

【C语言进阶】程序编译中的预处理操作

&#x1f4da;作者简介&#xff1a;爱编程的小马&#xff0c;正在学习C/C&#xff0c;Linux及MySQL.. &#x1f4da;以后会将数据结构收录为一个系列&#xff0c;敬请期待 ● 本期内容讲解C语言中程序预处理要做的事情 目录 1.1 预处理符号 1.2 #define 1.2.1 #define定义标识…

数据结构---线性表(顺序表)附代码

目录&#xff1a; 数据结构相关概念 1、什么是数据结构&#xff1f; 2、为什么需要数据结构&#xff1f; 顺序表 1、顺序表的概念及结构 1.1 线性表 1.2 顺序表 2、顺序表分类 3、动态顺序表的实现 什么是数据结构&#xff1f;&#xff1f; 数据结构是由 “数据”和 …

Unity 合并子物体获得简化Mesh

合并子物体获得简化Mesh &#x1f959;环境&#x1f96a;Demo &#x1f959;环境 PackageManager安装Editor Coroutines 导入插件&#x1f448; &#x1f96a;Demo 生成参数微调&#xff1a;Assets/EasyColliderEditor/Scripts/VHACDSettings/VHACDSettings.asset

MATLAB数值类型

MATLAB 数值 MATLAB支持各种数字类&#xff0c;包括有符号和无符号整数以及单精度和双精度浮点数。默认情况下&#xff0c;MATLAB将所有数值存储为双精度浮点数。 您可以选择将任何数字或数字数组存储为整数或单精度数字。 所有数值类型都支持基本数组运算和数学运算。 转换…

pyqt拖入图片并显示

pyqt拖入图片并显示 介绍效果代码 介绍 像拖入文本一样&#xff0c;把图片拖入到窗体中显示。 效果 代码 import sys from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout from PyQt5.QtGui import QPixmap, QDragEnterEvent, QDropEvent from PyQt5.Q…

Ollama配置webui连接大预言模型

Ollama配置Web UI连接大预言模型 默认ollama安装后&#xff0c;chat对话只有命令行界面&#xff0c;交互体验较差。借助open-webui可以通过web界面连接ollama&#xff0c;从而实现类似chatgpt式的web交互体验。 使用家用PC实践记录如下&#xff1a; 1. 环境配置 本次使用的操作…

笔记-mathtype公式在PDF或打印出来显示不全

原文中的公式&#xff1a; 纸质版打印出来的公式有缺失 问题描述&#xff1a;mathtype公式编辑器所编辑的公式转成PDF或者打印出来有缺失 以下是解决方法的具体描述。 目录 一、准备工作二、操作步骤 一、准备工作 1、工具&#xff1a;mathtype、微软word 二、操作步骤 …

数据可视化在不同行业中有哪些应用?

数据可视化即通过图表的形式将数据的内在信息有逻辑性地呈现给用户&#xff0c;使用户更容易发现数据中蕴藏的规律&#xff0c;找出问题&#xff0c;进而做出决策&#xff1b;另一方面&#xff0c;数据可视化项目也是一张重要的名片&#xff0c;是企业数字化建设效果的呈现。本…