中缀表达式转后缀表达式(逆波兰表达式)及如何计算后缀表达式

目录

中缀、后缀表达式简介

中缀转后缀的规则

模拟中缀转后缀 

中缀转后缀代码 

后缀表达式求值

后缀表达式求值代码

Leetcode相关题目 


中缀、后缀表达式简介

首先说说什么是中缀表达式,中缀表达式中,操作符是以中缀形式处于操作数的中间。例如,在表达式“3 + 4”中,“+”是中缀操作符,位于两个操作数“3”和“4”之间。对于我们而言,它最直观。下面说说后缀表达式,

逆波兰表达式(Reverse Polish Notation,RPN),也被称为后缀表达式,是一种算术表达式的表示方法。在这种表示法中,运算符被写在操作数的后面,而不是像常规的中缀表达式那样写在操作数的中间。逆波兰表达式不使用括号来指示运算的优先级,而是完全依赖于运算符出现的顺序以及运算符本身的优先级规则。也就是说,后缀表达式严格遵循从左往右计算。

中缀转后缀的规则

下面是中缀转后缀的思维导图,有一些细节不方便体现,我们到代码实现部分在谈。

模拟中缀转后缀 

根据上面思维导图中的规则,我们来模拟一下中缀转后缀。

希望通过上面的一个简单例子,我们明白了中缀转后缀的规则。上面被框起来的部分,是个细节,我在写代码的时候犯了这样的错误——我在把+出栈后,直接让-入栈,可把我坑惨了。出现错误后,我再次看了一遍代码,重点看了这一部分,但是觉得很对,一点都没错,哎。所以,我错在哪了?为什么不可以直接让-进栈?

我们在思考这个问题的时候不要局限于上面的图,因为照着上面的话感觉我犯的错误很对。

我错就错在我以为栈内就只有+这个运算符,+运算符出栈后,栈为空,所以直接把 - 运算符入栈。但实际上,栈内可能还有其他运算符,而且优先级低于或等于栈顶运算符。此时,应该让栈顶运算符出栈,而不是把 - 直接丢入栈内。也就是说,当前运算符 - 还要继续走前面运算符的逻辑。如果这句话暂时不能理解,没关系,看了代码就明白了。

下面我们上个看起来比较复杂的式子练练手。

其中,绿色的栈是递归时创建的。上面的例子值得好好理解。

中缀转后缀代码 

好了,我就不再废话了,上代码!

#include <iostream>
#include <vector>
#include <stack>
#include <map>
using namespace std;//下面需要比较优先级的高低,由于无法直接使用ASCII比较,故进行一下定义
map<char, int> pro = { {'+', 1}, {'-', 1}, {'*', 2}, {'/', 2} };void toRPN(const string& s, size_t& i, vector<string>& v)
{int n = s.size();stack<char> st;//存储操作符while (i < n){//isdigit为C语言的一个函数,功能是判断字符串中的某个字符是否是数字if (isdigit(s[i])){//细节:数字不一定是1位数,所以需要提取出完整的数字string tmp;while (i < n && isdigit(s[i])) tmp += s[i++];v.push_back(tmp);}else if (s[i] == '('){//递归处理i++;//跳过'('toRPN(s, i, v);}else if (s[i] == ')'){//结束递归while (!st.empty()){v.push_back(string(1, st.top()));//查文档——string的构造函数st.pop();}i++;//跳过')'return;}else{//走到这说明就是操作符了if (st.empty() || pro[st.top()] < pro[s[i]])st.push(s[i++]);else{v.push_back(string(1, st.top()));st.pop();//这里不能让i++,之前解释过了}}}//走到这,说明计算式或子表达式结束了,输出栈中所有运算符while (!st.empty()){v.push_back(string(1, st.top()));st.pop();}
}int main()
{vector<string> v;size_t i = 0;string s = "1+2-(3*4+5)-7";toRPN(s, i, v);for (auto s : v) cout << s << " ";cout << endl;return 0;
}

 到目前,你可能会疑惑会质疑,空格不需要处理吗?或者说有空格的话上面程序会不会崩掉?

空格是需要处理的,上面的函数是在处理完原字符串中的空格后再调用的,因为我不想在该函数内部处理空格,如果你想的话也可以,多加个判断就好了。

除了这个问题,代码中还有一个细节——仔细看看toRPN函数的参数。

我是不是都用了引用?因为我们希望程序在递归时处理的也是相同的字符串,递归时处理的结果也可以影响到上层,这是我们想要的。换句话说,s,i,v,为整个程序共用。

后缀表达式求值

前面在介绍后缀表达式的时候提到,后缀表达式严格按照从左到右计算。在计算后缀表达式时,我们需要借助一个栈(当然你可以用其他数据结构模拟栈)来存储数字。

 1 2 + 3 4 * 5 + - 7 -,以此表达式为例。

从左到右遍历表达式。

1)遇到运算数,直接入栈。

2)遇到操作符,取出栈中的两个操作数运算,运算结果存入中栈中。(细节下面说)

3)重复以上步骤,当遍历完表达式,栈顶元素即为答案。

有些操作符,比如 ‘-’ 和 ‘/’,它们是区分左右操作数的,即a - b 和 b - a 的结果可能不一样。这该怎么办?

栈的性质——后进先出。我们从左往右遍历,一定是左操作数先进栈,右操作数后进栈,所有先出的是右操作数,后出的是左操作数,这样就可以区分左右操作数了。其实,这就是选择栈来存储数据的原因。

后缀表达式求值代码

int calculate(vector<string>& s)
{stack<int> st;for (auto str : s){if (str == "+" || str == "-" || str == "*" || str == "/"){int right = st.top();st.pop();int left = st.top();st.pop();int ans = 0;switch (str[0]){case '+': ans = left + right; break;case '-': ans = left - right; break;case '*': ans = left * right; break;case '/': ans = left / right; break;}st.push(ans);}else{st.push(stoi(str));}}return st.top();
}
int main()
{vector<string> v;size_t i = 0;string s = "1+2-(3*4+5)-7";toRPN(s, i, v);cout << calculate(v) << endl;return 0;
}

Leetcode相关题目 

. - 力扣(LeetCode)

上面这题可以我们本片博客讲到的方法解决,虽然不是最简洁的解法,但是可以练练我们上面讲到的方法。代码我在下面贴一份。

class Solution {
public:int calculate(string s) {vector<string> v;stack<int> st;size_t i = 0;toRPN(s, i, v);for(auto& str : v){if(str == "+" || str == "-" || str == "*" || str == "/"){int right = st.top();st.pop();int left = st.top();st.pop();int ans = 0;switch(str[0]){case '+': ans = left + right; break;case '-': ans = left - right; break;case '*': ans = left * right; break;case '/': ans = left / right; break;}st.push(ans);}else{st.push(stoi(str));}}return st.top();}//中缀转后缀map<char, int> pro = { {'+', 1}, {'-', 1}, {'*', 2}, {'/',2} };void toRPN(const string& s, size_t i, vector<string>& v){int n = s.size();stack<char> st;while(i < n){if(s[i] == ' ') i++;else if(isdigit(s[i])){//提取数字string tmp;while(i < n && isdigit(s[i])) tmp += s[i++];v.push_back(tmp);}else{if(st.empty() || pro[s[i]] > pro[st.top()])st.push(s[i++]);else{v.push_back(string(1, st.top()));st.pop();}}}while(!st.empty()){v.push_back(string(1, st.top()));st.pop();}}
};

本篇文章到这就结束啦~如有错误,请您不吝指出,谢谢!

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

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

相关文章

Linux安装Anaconda和Pytorch

又到了一年一度换环境、换服务器不断折腾的时节了&#xff0c;一通折腾后&#xff0c;重新启动遂做记录。 1. Linux安装Anaconda 1.1 离线安装模式 进入官网https://www.anaconda.com/download/success&#xff0c;如图所示&#xff1a; 选择版本进行下载即可。 1.2 在线w…

[Linux网络编程]03-TCP协议

一.TCP协议数据通信的过程 TCP数据报如下&#xff0c;数据报中的标志位双端通信的关键。 三次握手: 1.客户端向服务端发送SYN标志位&#xff0c;请求建立连接&#xff0c;同时发送空包 2.服务端向客户端回发ACK标志位(即确认标志位&#xff0c;任何一端发送数据后都需要另一端…

【VUE】【IOS】【APP】IOS Music APP播放器开发

前言 周末闲来无事&#xff0c;学习了下移动端的一些知识。了解到移动端的一些实现方式&#xff0c;先从最简单的开始。本人没有IOS swift 和Android的开发经验。抱着学习态度从简单的入手&#xff0c;经过了解&#xff0c;本人之前自己用vue的写着玩了几个小项目。看到可以用…

《使用Gin框架构建分布式应用》阅读笔记:p101-p107

《用Gin框架构建分布式应用》学习第7天&#xff0c;p101-p107总结&#xff0c;总计7页。 一、技术总结 1.StatusBadRequest vs StatusInternalServerError 写代码的时候有一个问题&#xff0c;什么时候使用 StatusBadRequest(400错误)&#xff0c;什么时候使用 StatusIntern…

1.2电子商务安全内涵

目录 1 电子商务安全的层次 2 计算机网络安全 3电子商务安全的特点 只有在你生命美丽的时候&#xff0c;世界才是美丽的。 —— 顾城 《顾城哲思录》 1 电子商务安全的层次 安全:主体没有危险的客观状态 电子商务安全是一个广泛的概念&#xff0c;它涉及到电子商务的各个方…

现今 CSS3 最强二维布局系统 Grid 网格布局

深入学习 CSS3 目前最强大的布局系统 Grid 网格布局 Grid 网格布局的基本认识 Grid 网格布局: Grid 布局是一个基于网格的二位布局系统&#xff0c;是目前 CSS 最强的布局系统&#xff0c;它可以同时对列和行进行处理&#xff08;它将网页划分成一个个网格&#xff0c;可以任…

PHP函数$_FILES详解

PHP函数$_FILES详解 在PHP中上传一个文件建一个表单要比ASP中灵活得多。具体的看代码。 <form enctype"multipart/form-data" action"upload.php" method"post"> <input type"hidden" name"MAX_FILE_SIZE" value…

嵌入式入门学习——8基于Protues仿真Arduino+SSD1306液晶显示数字时钟

0 系列文章入口 嵌入式入门学习——0快速入门&#xff0c;Let‘s Do It&#xff01; SSD1306 1 Protues查找SSD1306器件并放置在画布&#xff0c;画好电气连接&#xff08;这里VCC和GND画反了&#xff0c;后面仿真出错我才看见&#xff0c;要是现实硬件估计就烧毁了&#xf…

【时时三省】(C语言基础)函数介绍strncat

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 strncat 打印结果是hello wor 跟strcat不同的是他后面可以加一个参数 这个参数就是它可以根据后面的数字 来追加多少个字符 这个如果后面的参数改成10的话 就是打印hello world 不会跟strn…

Appium环境搭建、Appium连接真机

文章目录 一、安装Android SDK二、安装Appium-desktop三、安装Appium Inspector 一、安装Android SDK 首先需要安装jdk&#xff0c;这里就不演示安装jdk的过程了 SDK下载地址&#xff1a;Android SDK 下载 1、点击 Android SDK 下载 -> SKD Tools 2、选择对应的版本进行下…

诊断知识:NRC78(Response Pending)的回复时刻

文章目录 前言NRC78的使用场景客户需求解读Autosar Dcm中的定义工具链中的配置总结 前言 在项目开发过程中&#xff0c;客户变更需求&#xff0c;是关于NRC78的回复时间点的&#xff0c;该需求在Autosar Dem中也有对应的参数&#xff0c;DcmTimStrP2ServerAdjust&#xff08;针…

Cortex-A7:如何切换ARM和Thumb状态

0 参考资料 ARM Cortex-A(armV7)编程手册V4.0.pdf1 Cortex-A7&#xff1a;如何切换ARM和Thumb状态 1.1 Cortex-A7支持的指令集 Cortex-A7支持的指令集包括ARM指令集和Thumb-2&#xff08;ARM官方一般用Thumb表示&#xff09;指令集。 ARM指令集指令大小都是32位&#xff0c;…

CLion和Qt 联合开发环境配置教程(Windows和Linux版)

需要安装的工具CLion 和Qt CLion下载链接 :https://www.jetbrains.com.cn/clion/ 这个软件属于直接默认安装就行&#xff0c;很简单&#xff0c;不多做介绍了 Qt:https://mirrors.tuna.tsinghua.edu.cn/qt/official_releases/online_installers/ window 直接点exe Linux 先c…

【一种比较万能的方法删除磁盘里删除不了的文件】

一种比较万能的方法删除磁盘里删除不了的文件 只需要以下三步&#xff1a; 1、运行命令提示符&#xff08;以管理员身份打开&#xff09; 2、修复磁盘文件&#xff0c;运行命令 chkdsk 文件所在目录 /f 3、del 文件所在目录

手写Spring IOC-简易版

目录 项目结构entitydaoIUserDaoUserDaoImpl serviceIUserServiceUserServiceImpl ApplicationContext 配置文件初始化 IOC 容器RunApplication 注解初始化 IOC 容器BeanAutowired Reference 项目结构 entity User Data NoArgsConstructor AllArgsConstructor Accessors(chai…

计算DOTA文件的IOU

背景 在目标检测任务中&#xff0c;评估不同对象之间的重叠情况是至关重要的&#xff0c;而IOU&#xff08;Intersection Over Union&#xff09;是衡量这种重叠程度的重要指标。本文将介绍如何编写一个Python脚本&#xff0c;通过并行化处理DOTA格式的标注文件&#xff0c;统…

JDK17下,使用SHA1算法报Certificates do not conform to algorithm constraints错误

JDK17从17.0.5开始&#xff0c;默认不再允许使用SHA1算法&#xff0c;如果引用的jar包或代码里使用了SHA1算法&#xff0c;会报以下错误。 Caused by: javax.net.ssl.SSLHandshakeException: Certificates do not conform to algorithm constraintsat java.base/sun.security.…

演示:基于WPF的DrawingVisual开发的高刷新率示波器

一、目的&#xff1a;分享一个基于WPF的DrawingVisual开发的高刷新率示波器 二、效果演示 特此说明&#xff1a;由于Gif录制工具帧率不够&#xff0c;渲染60帧用了4.6秒&#xff0c;平均帧率在12Hz左右&#xff0c;所以展示效果不好&#xff0c;想要看好些的效果可以看文章下面…

python中堆的用法

Python 堆&#xff08;Headp&#xff09; Python中堆是一种基于二叉树存储的数据结构。 主要应用场景&#xff1a; 对一个序列数据的操作基于排序的操作场景&#xff0c;例如序列数据基于最大值最小值进行的操作。 堆的数据结构&#xff1a; Python 中堆是一颗平衡二叉树&am…

每日OJ题_牛客_集合_排序_C++_Java

目录 牛客_集合_排序 题目解析 C代码 Java代码 牛客_集合_排序 集合_牛客题霸_牛客网 (nowcoder.com) 题目解析 笔试题可直接用set排序&#xff0c;面试可询问是否要手写排序函数&#xff0c;如果要手写排序&#xff0c;推荐写快排。 C代码 #include <iostream> …