题目:输入一个中缀表达式,计算其结果。
输入的前提假设:
(1)只考虑+、-、*、/这四种运算符,中缀表达式中只有一种括号:();
(2)输入的中缀表达式中只有整数,没有小数;
(3)假定输入是合法的。
一、如何将中缀表达式转化为后缀表达式
在日常应用中,算术表达式中运算符总是出现在两个操作数之间,例如5*(7-23)+8/2,这种形式称为中缀表达式。计算一个中缀表达式需要知道运算符的优先级和结合性。乘除是高优先级,加减是低优先级,优先级相同时他们都是左结合的,也就是从左计算到右。有括号就要计算括号内的表达式。
中缀表达式利于人的理解,但不便于计算机的处理。因此需要将中缀表达式转换成后缀表达式,以方便计算机处理。所谓后缀表达式就是将运算符放在运算数之后。后缀表达式也称为逆波兰表达式。
比如:
中缀表达式为:
对应后缀表达式为:
如何将一个中缀表达式转化为后缀表达式?我们需要借助栈的力量,用它来存放运算符。算法流程如下:
首先将各种运算符(包括括号)的优先级排列如下(数字越大,优先级越高):
1:(
2:+ -
3: /
4:)
对输入的中缀表达式从左到右遍历:
1)如果遇到数字,直接添加到后缀表达式末尾;
2)如果遇到运算符+、-、*、/:
先判断栈是否为空。若是,则直接将此运算符压入栈。若不是,则查看当前栈顶元素。若栈顶元素优先级大于或等于此操作符级别,则弹出栈顶元素,将栈顶元素添加到后缀表达式中,并继续进行上述判断。如果不满足上述判断或者栈为空,将这个运算符入栈。要注意的是,经过上述步骤,这个运算符最终一定会入栈。
3)如果遇到括号:
如果是左括号,直接入栈。如果是右括号,弹出栈中第一个左括号前所有的操作符,并将左括号弹出。(右括号别入栈)。
4)字符串遍历结束后,如果栈不为空,则弹出栈中所有元素,将它们添加到后缀表达式的末尾,直到栈为空。
二、计算后缀表达式
后缀表达式的计算就相当简单了。准备一个数字栈。从左到右扫描后缀表达式,如果是数字,放入数字栈。如果是符号,从数字栈中弹出两个数字,第一个取出的数字为右运算数,第二个为左运算数,进行运算。然后将结果放进数字栈中。如此反复,直到读完整个表达式后,留在数字栈中的那个数字就是最终结果。
三、代码如下:
#include <bits/stdc++.h>
using namespace std;
int main(){
map<char,int>p;
p['('] = 1;
p['+'] = 2; p['-'] = 2;
p['*'] = 3; p['/'] = 3;
p[')'] = 4;
string s;
ifstream cin("input.txt");
while(cin >> s){
//中缀转后缀
vector<int>result;
stack<char>op;
int t = 0;
for(int i = 0; i < s.size(); i++){
if(isdigit(s[i])){
t = t * 10 + s[i] - '0';
if(i+1<s.size() && !isdigit(s[i+1])){
result.push_back(t);
t = 0;
}
}
else{
if(s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/'){
if(op.size() <= 0){
op.push(s[i]);
}else{
while(op.size() > 0 && p[op.top()] >= p[s[i]]){
result.push_back((int)op.top());
op.pop();
}
op.push(s[i]);
}
}
else if(s[i] == '('){
op.push(s[i]);
}else{
while(op.top() != '('){
result.push_back((int)op.top());
op.pop();
}
op.pop();
}
}
}
while(op.size() > 0){
result.push_back((int)op.top());
op.pop();
}
// for(auto i : result){
// if(i>=40)cerr<<(char)i<<" ";
// else
// cerr << i << " ";
// }
//计算后缀式
stack<int>sk;
for(int i = 0; i < result.size(); i++){
if(result[i] == '+' || result[i] == '-' || result[i] == '*' || result[i] == '/'){
int b = sk.top(); sk.pop();
int a = sk.top(); sk.pop();
int c;
if(result[i] == '+'){
c = a + b;
}else if(result[i] == '-'){
c = a - b;
}else if(result[i] == '*'){
c = a * b;
}else {
c = a / b;
}
sk.push(c);
}else{
sk.push(result[i]);
}
}
cout << sk.top() << endl;
}
}
样例输入
4+23-10/5#
3(7-2)#
2*3/2#
样例输出
8
15
3