栈的表达式求值中的应用——逆波兰表达式求值+中缀表达式转后缀表达式

2024-05-04 13:52

本文主要是介绍栈的表达式求值中的应用——逆波兰表达式求值+中缀表达式转后缀表达式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 1. 逆波兰表达式(后缀表达式)求值
    • 思路讲解
    • AC代码
  • 2. 中缀表达式转后缀表达式
    • 分析
    • 方法总结
  • 3. 中缀表达式求值

1. 逆波兰表达式(后缀表达式)求值

链接: link
在这里插入图片描述

这道题目叫做逆波兰表达式求值,那什么是逆波兰表达式呢
我们可以一起来了解一下:
在这里插入图片描述
结合题目中给的测试用例给大家解释一下:
在这里插入图片描述
我们正常写的表达式,就比如题目中的这个:(2 + 1) * 3
这种写法叫做中缀算术表达式,即运算符写在操作数的中间,但是这种写法计算机是不能直接计算的,因为涉及运算符优先级的问题,比如1+2*3,应该先算*
所以呢,这里就需要我们做一件事情,就是把它变成后缀表达式,其实就是根据优先级对表达式中的运算符排一个序,并且放到对应的操作数后面。
就比如题目中给的这个示例:((2 + 1) * 3)这个表达式对应的后缀表达式就是["2","1","+","3","*"](题中是把它放到一个字符串数组中了)。
即1和2先进行后面的+,得到的结果再和3进行后面的*,得到最终结果。这样就直接从前往后算,不用考虑优先级的问题了。

那现在大家对逆波兰表达式应该有一个大致的了解了。

思路讲解

但是呢,单要解这道题目的话,其实很好搞:

我们只需要借助一个栈就搞定了。
具体怎么做呢?
我们去遍历给的逆波兰表达式对应的字符串数组,如果对应的元素是数字,我们就让该操作数入栈,如果遇到操作符,我们就去取栈顶的前两个元素(并pop掉)进行对应的运算(第一个是右操作数,第二个是左操作数),然后将结果入栈,后续重复上述操作,最终栈里面唯一的那个元素就是要求的结果。
举个栗子:
在这里插入图片描述
遍历tokens,2 1入栈,接着遇到+,取出 1 2相加,得到结果3入栈,后面又是一个3入栈,接着遇到* ,取出3 3相乘,结果9入栈。
最终栈里面唯一的元素9就是结果。

AC代码

在这里插入图片描述

class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> st;for(auto& str:tokens){if(str=="+"||str=="-"||str=="*"||str=="/"){int right=st.top();st.pop();int left=st.top();st.pop();switch(str[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;}}else{st.push(stoi(str));}}return st.top();}
};

在这里插入图片描述

2. 中缀表达式转后缀表达式

那现在大家再来思考一个问题:
如果给我们一个中缀表达式,我们如何把它转换成对应的后缀表达式

分析

中缀转后缀呢,也是需要借助一个栈,具体怎么做呢?
比如现在有这样一个中缀表达式1+2*3-4
怎么把它转成后缀呢?
🆗,我们还是从头去遍历这个表达式,如果遇到的是操作数,就输出
在这里插入图片描述
如果遇到的是的是操作符,那这时要分情况进行分析:
如果此时栈为空,就让该操作符进栈;

在这里插入图片描述
在这里插入图片描述
如果遇到的是操作符,且此时栈不为空,则取栈顶的操作符与当前操作符比较,比较啥呢——优先级:
如果比栈顶操作符优先级高,就让该操作符进栈,为什么是进栈而不是拿它进行运算呢?
因为后面有可能还有优先级更高的,所以先进栈。

在这里插入图片描述
那进栈之后呢?继续取下一个进行判断是操作数还是操作符。
在这里插入图片描述
如果比栈顶操作符优先级低或者相等,则出栈顶的操作符输出(即此时栈顶的这个操作符可以进行运算了)
在这里插入图片描述
然后再去判断栈是否为空,不为空再拿当前操作符和栈顶操作符比较,进行相应操作,为空就入栈。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
遍历结束后,如果栈不为空,将剩余操作符输出。
在这里插入图片描述
此时,就得到对应的后缀表达式了。
在这里插入图片描述

但是,如果是带括号的情况呢?

比如1+2*(4-5)+6/7,怎么处理?
🆗,那如果按照上面的分析,1输出,+入栈,2输出,*的优先级比栈顶的+高,*也入栈,接着遇到了括号,怎么办?
在这里插入图片描述
如果不加括号的话,后面-比*优先级低,那应该让*先出栈运算,但是现在-在括号里面,所以-应该先运算,所以要认为-的优先级更高。
那我们可以怎么处理呢?当然这里的方法可能不止一种,我们可以这样做:
遇到(,我们认为它的优先级很低,但是我们不拿(做比较,直接让它入栈
在这里插入图片描述
然后遇到括号里的-,栈不为空,比较,因为我们说了认为(的优先级很低,所以-也入栈
在这里插入图片描述
那继续往后走遇到)怎么办?
🆗,)呢我们也认为它的优先级很低,但是)我们要拿它去比较,因为我们认为)优先级很低,所以此时栈顶的-是不是就被成功弹出了。
在这里插入图片描述
然后栈不为空继续跟栈顶比,那此时) 就遇到 (了,拿这时怎么做呢?
这时直接把(pop掉,不输出,然后跳过) 继续看下一个,因为后缀表达式优先级都排好了就不需要括号了。

在这里插入图片描述
拿继续往后走遇到+,栈不为空,跟栈顶比,比栈顶优先级低,栈顶操作符*输出,继续栈还不为空,继续比,优先级相等,出栈顶操作符+
在这里插入图片描述
然后栈空了,+入栈
在这里插入图片描述
然后遇到6输出,遇到/优先级比+高,入栈,然后7输出
在这里插入图片描述
就遍历完了,再把剩余操作符输出
在这里插入图片描述
就得出结果后缀表达式了,大家可以验证一下。

在这里插入图片描述
当然处理括号可能有很多种方法,我们这里提供的只是其中一种,而且我们这种方法如果遇到有些极端的情况可能也不一定处理的了,可能还需要加一些特殊处理。
另外我们会发现就是遇到(是不是好像去开了一个新栈,在这个新栈里去处理括号里的这个子表达式,所以如果这样的问题也可以考虑递归去搞,每次遇到(就递归去处理这个子表达式,处理完回去递归调用的地方继续处理后面的。

方法总结

在这里插入图片描述

3. 中缀表达式求值

那大家再来思考一下,如果给一个中缀表达式,我们该如何求它的值呢?

🆗,是不是就是上面两种操作的结合啊。
在这里插入图片描述

这篇关于栈的表达式求值中的应用——逆波兰表达式求值+中缀表达式转后缀表达式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/959351

相关文章

5分钟获取deepseek api并搭建简易问答应用

《5分钟获取deepseekapi并搭建简易问答应用》本文主要介绍了5分钟获取deepseekapi并搭建简易问答应用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需... 目录1、获取api2、获取base_url和chat_model3、配置模型参数方法一:终端中临时将加

JavaScript中的isTrusted属性及其应用场景详解

《JavaScript中的isTrusted属性及其应用场景详解》在现代Web开发中,JavaScript是构建交互式应用的核心语言,随着前端技术的不断发展,开发者需要处理越来越多的复杂场景,例如事件... 目录引言一、问题背景二、isTrusted 属性的来源与作用1. isTrusted 的定义2. 为

Python调用另一个py文件并传递参数常见的方法及其应用场景

《Python调用另一个py文件并传递参数常见的方法及其应用场景》:本文主要介绍在Python中调用另一个py文件并传递参数的几种常见方法,包括使用import语句、exec函数、subproce... 目录前言1. 使用import语句1.1 基本用法1.2 导入特定函数1.3 处理文件路径2. 使用ex

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

将Python应用部署到生产环境的小技巧分享

《将Python应用部署到生产环境的小技巧分享》文章主要讲述了在将Python应用程序部署到生产环境之前,需要进行的准备工作和最佳实践,包括心态调整、代码审查、测试覆盖率提升、配置文件优化、日志记录完... 目录部署前夜:从开发到生产的心理准备与检查清单环境搭建:打造稳固的应用运行平台自动化流水线:让部署像

Python在固定文件夹批量创建固定后缀的文件(方法详解)

《Python在固定文件夹批量创建固定后缀的文件(方法详解)》文章讲述了如何使用Python批量创建后缀为.md的文件夹,生成100个,代码中需要修改的路径、前缀和后缀名,并提供了注意事项和代码示例,... 目录1. python需求的任务2. Python代码的实现3. 代码修改的位置4. 运行结果5.

Linux中Curl参数详解实践应用

《Linux中Curl参数详解实践应用》在现代网络开发和运维工作中,curl命令是一个不可或缺的工具,它是一个利用URL语法在命令行下工作的文件传输工具,支持多种协议,如HTTP、HTTPS、FTP等... 目录引言一、基础请求参数1. -X 或 --request2. -d 或 --data3. -H 或

在Ubuntu上部署SpringBoot应用的操作步骤

《在Ubuntu上部署SpringBoot应用的操作步骤》随着云计算和容器化技术的普及,Linux服务器已成为部署Web应用程序的主流平台之一,Java作为一种跨平台的编程语言,具有广泛的应用场景,本... 目录一、部署准备二、安装 Java 环境1. 安装 JDK2. 验证 Java 安装三、安装 mys

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一