中缀表达式利于我们手动计算,对于计算机而言,后缀表达式更利于计算机计算。
那么,如何将中缀表达式转换为后缀表达式,按照以下步骤即可。
①按照运算符的优先级对所有运算符和它的运算数加括号(原本有括号的就不用再加了)
②把运算符移动到对应的括号后
③去掉括号
同样的,将中缀表达式转化为前缀表达式,与上述过程类似:
①按照运算符的优先级对所有运算符和它的运算数加括号(原本有括号的就不用再加了)
②把运算符移动到对应的括号前
③去掉括号
#include<iostream>
#include<string>
#include<stack>
using namespace std;
// 将所有括号都转为()
string convertSTR(string str) {
for (int i = 0; i < str.size(); i++) {
if (str[i] == '[' || str[i] == '{')
str[i] = '(';
if (str[i] == ']' || str[i] == '}')
str[i] = ')';
}
return str;
}
int compute(int a, int b, char opera) {
int result = 0;
switch (opera) {
case '+': result = a + b; break;
case '-': result = a - b; break;
case '*': result = a * b; break;
case '/': result = a / b; break;
}
return result;
}
int computing(string str) {
int flag = 0; // 用来记录正负号,0表示无符号,1表示正号,2表示负号
stack<int> nums;
stack<char> operas;
for (int i = 0; i < str.size(); i++)
{
if (isdigit(str[i])) { //int isdigit(int c) 检查所传的字符是否是十进制数字字符
// 如果当前位为数字,需要看看这个数字变成int有多大,正负号的问题,
//等到了+-的时候处理
int j = i, num = 0;
// 这里需要一个循环依次往后判断
while (i + 1 < str.size() && isdigit(str[i + 1])) i++;
// 这里使用i++目的是为了找到这个数字的最后一位之后
string str_num = str.substr(j, i - j + 1); //把获取到的这个数字存入字符串str
for (int k = 0; k < str_num.size(); k++) //要把这个字符串转变为数字
num = num * 10 + str_num[k] - '0';
if (flag == 2)
num = 0 - num;
flag = 0; // 使用完毕这个数字正负号之后归为0
// 把这个数字放到数字栈
nums.push(num);
}
else if (str[i] == '*' || str[i] == '/' || str[i] == '(')
{
// 直接放到符号栈
operas.push(str[i]);
}
else if (str[i] == '+' || str[i] == '-')
{
// 先要判断是不是数字的正负号
if (i == 0 || str[i - 1] == '(')
{
if (str[i] == '+')
flag = 1;
else
flag = 2;
}
// 遇到加减号的时候,先进行计算,保证其他乘除号的优先级
while (flag == 0 && !operas.empty() && operas.top() != '(')
{
// 进行计算的三个条件
// 堆栈非空时,符号栈弹出符号,并结合数字栈计算
int b = nums.top();
nums.pop();
int a = nums.top();
nums.pop();
char opera = operas.top();
operas.pop();
nums.push(compute(a, b, opera));
}
// 然后把这个加减号放入符号栈(如果这个是加减号不是正负号的话)
if (flag == 0)
operas.push(str[i]);
}
else if (str[i] == ')') {
// 一直计算,直到计算到左括号
while (operas.top() != '(') {
int b = nums.top();
nums.pop();
int a = nums.top();
nums.pop();
char opera = operas.top();
operas.pop();
nums.push(compute(a, b, opera));
}
// 计算完之后把左括号从符号栈退出
operas.pop();
}
}
// 最后把符号栈和数字栈中的执行运算,输出结果
while (!operas.empty()) {
int b = nums.top();
nums.pop();
int a = nums.top();
nums.pop();
char opera = operas.top();
operas.pop();
nums.push(compute(a, b, opera));
}
// 最后返回结果,也就是退出数字栈的仅存的一个元素
return nums.top();
}
int main() {
string str;
while (cin >> str) {
str = convertSTR(str);
cout << computing(str) << endl;
}
return 0;
}
关于此处中缀表达式与后缀表达式的转换计算问题,可以参照胡凡的《算法笔记》的“栈的应用”部分,给出的例题可以参照学习一下。