表达式求值(中后缀知识恶补)
作者:互联网
acwing3302
良好的观看体验
题意:
给你一个表达式,叫你求出这个表达式的值,表达式由数字括号和一元运算符构成。
在数据结构的课本中有过相对应的例题,其实就是利用表达式的前中后缀来求表达式的值。
那么相应的三个问题就伴随产生:
1.前后缀表达式相比中缀表达式的优点是什么呢?
2.怎么样才能将中缀表达式转化成后缀表达式呢?
2.如果变成了后缀表达式又该怎么计算呢?
后缀小知识:
20世纪50年代,波兰逻辑学家Jan Łukasiewicz想到了一种不需要括号的后缀表示法,我们称之为逆波兰表示(Reverse Polish Notation, RPN),非常巧妙地解决了程序实现四则运算的难题。
优点:
后缀表达式不需要括号也可以进行加减乘除四则运算,那么这样就优化了运算过程,把括号去掉了。
将中缀表达式转换成等价的后缀表达式后,求值时,不需要再考虑运算符的优先级,只需从左到右扫描一遍后缀表达式即可
中缀转后缀方法:
1.从左到右将遇到的运算符入栈,遇到操作数直接将入栈(对应栈有两个一个存数字,一个存字符)
2.在将运算符入栈的时候先看看是否即将入栈的运算符优先级是否高于栈顶运算符的优先级,如果高则直接入,如果低,那么就进行出栈,直到栈顶的运算符优先级低于即将要入的运算符优先级,将弹出的运算符 跟在刚刚的操作数后面就行。
3.如果入栈的时候运算符是右括号那么就出栈,直到出栈遇到左括号再停止出栈。
后缀表达式的计算方法
与前缀表达式类似,只是顺序是从左至右:
从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,
用运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果入栈;
重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果
C++ 代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<unordered_map>
#include<stack>
using namespace std;
unordered_map<char,int> h{{'+',1},{'-',1},{'*',2},{'/',2}};
stack<int> num;
stack<char> op;
void eval()
{
int b = num.top(); //第二个操作数
num.pop();
int a = num.top(); //第一个操作数
num.pop();
char c = op.top(); //运算符
op.pop();
int x = 0;
if (c == '+') x = a+b;
if (c == '-') x = a-b;
if (c == '*') x = a*b;
if (c == '/') x = a/b;
num.push(x); //结果入栈
}
int main()
{
string s;
cin>>s;
for(int i=0;i<s.size();i++)
{
if(isdigit(s[i])) //补充说明:isdigit是一个判断是否为数字的bool函数
{
int x=0,j=i;
while(j<s.size()&&isdigit(s[j]) )
{
x=x*10+ s[j]-'0' ;
j++;
}
num.push(x);
i=j-1; //因为碰到不是数字的运算符会停止,但是for会将i ++,所以要减一
}
else if(s[i]=='(')
{
op.push(s[i]);
}
else if(s[i]==')')
{
while(op.top()!='(')
eval();
op.pop();
}
else
{
while(op.size()&&h[s[i]] <= h[op.top()]) //顺序不可变,因为如果栈没有元素那么会出现错误
{ //当栈元素个数为0时强行取栈顶会出现内存错误
eval();
}
op.push(s[i]);
}
}
while(op.size()) //最后的运算符不要忘记了
{
eval();
}
cout<<num.top()<<endl;
return 0;
}
如果有什么错误的地方请指出,谢谢。
代码是自己对着视频和看其他人的题解写的,不是作者本身写的,向各位大佬学习。。
(标记的细节是作者犯得错误和查的知识)
标签:恶补,后缀,运算符,num,求值,include,表达式,入栈 来源: https://blog.csdn.net/weixin_51626694/article/details/118637674