#include<iostream>
#include<stack>
#include<string>
using namespace std;
/*
1.建立符号栈
2.顺序扫描中序表达式
a) 是数字, 直接输出
b) 是运算符
i : “(” 直接入栈
ii : “)” 将符号栈中的元素依次出栈并输出, 直到 “(“, “(“只出栈, 不输出
iii: 其他符号, 将符号栈中的元素依次出栈并输出, 直到遇到比当前符号优先级更低的符号或者”(“。 将当前符号入栈。
3.扫描完后, 将栈中剩余符号依次输出
*/
bool priority(char ch1, char ch2){//优先级判断
if(ch2 == '(') return true;
if(ch1 == '+' || ch1 == '-') return false;
if(ch1 == '*' || ch1 == '/') return true;
}
string mid_back(string s){//计算后缀表达式
string res;
stack<char> st;
for(int i = 0; i < s.size(); i++){
if(s[i] >= '0' && s[i] <= '9') res += s[i];
if(s[i] == '(') st.push(s[i]);
if(s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/'){
if(st.empty()) st.push(s[i]);//栈空时,直接压入
else
while(1){
char temp = st.top();
if(priority(s[i], temp)){//当前算术符号高于栈顶算术符号优先级
st.push(s[i]);
break;
}
else{
res += temp;//将栈顶算术符号放入算术表达式
st.pop();//直到当前算术符号优先级小于栈顶算术符号
if(st.empty()){
st.push(s[i]);
break;
}
}
}
}
if(s[i] == ')'){//直到括号内,全部出栈
while(st.top() != '('){
res += st.top();
st.pop();
}
st.pop();
}
}
while(!st.empty()){//剩余的符号
res += st.top();
st.pop();
}
return res;
}
int clc(string s){//计算后缀表达式
stack<int> st;
for(int i = 0; i < s.size(); i++){
if(s[i] >= '0' && s[i] <= '9')//数字压入栈
st.push(s[i] - '0');
else{//遇到字符,数字出栈
int num2 = st.top(); st.pop();
int num1 = st.top(); st.pop();
if(s[i] == '+') st.push(num1+num2);
if(s[i] == '-') st.push(num1-num2);
if(s[i] == '*') st.push(num1*num2);
if(s[i] == '/') st.push(num1/num2);
}
}
return st.top();
}
int main(){
string s, s2;
cin >> s;
s2 = mid_back(s);//后缀表达式
cout << clc(s2) << endl;//计算结果
return 0;
}
例如表达式:#2*(3+4)-6/3#,运行的输出结果为12。
方法一:
关于中缀表达式向后缀表达式的过程
2 | 23 | 23 | 234+ | 234+* | 234-*63/ | 234-*63/- |
*( | *(+ | * | - | - |
后缀表达式计算
2 3 4 + | 2 7 | 14 6 3 | 14 2 | 12 |
3+4 | * | / | - |
方法二:
也可以使用两个栈。一个存符号,一个存数字。
即将mid_back()与clc()合并,再加上一个栈(即数字栈),便可。