注:本博客是基于《数据结构》这门课,主要是为了自己考研,准备专业课
图解转自:中缀转后缀算法
中缀转后缀算法
中缀表达式转后缀表达式遵循以下原则:
- 遇到操作数,直接输出
- 当栈为空时,若遇到运算符,则入栈
- 当遇到左括号 “(” 时,则将其入栈
- 当遇到右括号 “)” 时,执行出栈操作,将栈顶的元素输出,直到栈顶元素是左括号时弹出并停止,左括号不输出
- 当遇到其他运算符如“+”、“-”、“ * ” 、“ / ”时,弹出栈中所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈
- 最后,再将栈中的元素依次出栈,输出
- 经过上面的步骤,得到的输出既是转换得到的后缀表达式
⚠️ 运算符优先级: { *,/ } > { +,— } > { ( }
举例:a+b * c+(d * e+f) * g ——> abc * +de * f+g * +
图示上述过程:
遇到a,直接输出:
遇到+,此时栈为空,入栈:
遇到b,直接输出:
遇到*,此时其优先级大于栈顶符号+的优先级,则入栈:
遇到c,输出:
遇到+,目前站内的* 、+优先级都大于或等于它,因此将栈内的* 、+依次弹出并且输出,并且将这个+入栈:
遇到(,将其入栈:
遇到d,直接输出:
遇到*,由于其优先级高于处在栈顶的(,因此直接入栈:
遇到e,直接输出:
遇到+,此时栈顶的*优先级高于+,但是栈内的( 优先级低于 +,故将 * 出栈输出,+入栈:
遇到f,直接输出:
遇到 ),弹出栈顶元素并且输出,直到遇到( 才结束,在这里也就是弹出+输出,弹出(不输出:
遇到*,优先级高于栈顶+,将*入栈
遇到g,直接输出:
此时中缀表达式已全部处理完成,故依次将栈中元素出栈并输出,直到栈为空:
代码部分:
//中缀表达式转后缀表达式
#include<iostream>
#include<string>
#include<stack>
using namespace std;
int prio(char op) { //给运算符优先级排序
int priority=0;
if (op == '*' || op == '/')
priority = 2;
if (op == '+' || op == '-')
priority = 1;
if (op == '(')
priority = 0;
return priority;
}
bool Trans(string& str1, string& str2) { //引用传递
stack<char> s; //定义一个char类型的栈s
int i;
for (i = 0; i < str1.size(); i++)
{
if (str1[i] >= '0' && str1[i] <= '9') { //如果是数字,直接入栈
str2 += str1[i];
}
else //否则不是数字
{
if (s.empty()) //栈空则入站
s.push(str1[i]);
else if (str1[i] == '(') //左括号入栈
s.push(str1[i]);
else if (str1[i] == ')') { //如果是右括号,只要栈顶不是左括号,就弹出并输出
while (s.top() != '(') {
str2 += s.top();
s.pop();
}
s.pop(); //弹出左括号,但不输出
}
else { //当栈顶非空时
while (prio(str1[i]) <= prio(s.top())) { //当栈顶优先级大于等于当前运算符,输出
str2 += s.top();
s.pop();
if (s.empty()) //栈为空,停止
break;
}
s.push(str1[i]); //把当前运算符入栈
}
}
}
while (!s.empty()) { //最后,如果栈不空,则弹出所有元素并输出
str2 += s.top();
s.pop();
}
return true;
}
int main() { //主程序
string infix; //保存输入的中缀表达式
string postfix;
cout << "请输入中缀表达式:" << infix << endl;
cin >> infix;
Trans(infix, postfix);
cout << "后缀表达式为:" << postfix << endl;
system("pause");
return 0;
}
后缀表达式计算思路:
从左往右依次扫描后缀表达式,遇到操作数入栈,遇到运算符、则弹出两个操作数、计算结果并将结果入栈( 注:先弹出的为右操作数,后弹出的为左操作数),循环以上过程,直到扫描完后缀表达式,此时栈中的数即为运算结果。
图解:
实例:
输入: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]
输出: 22
解释:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
具体实现:
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> numbers;
for(int i = 0 ; i < tokens.size() ;i++){
//若为运算符,则弹出两个栈顶元素,进行运算并将结果放回栈
if(tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/"){
int res;
int n2 = numbers.top();
numbers.pop();
int n1 = numbers.top();
numbers.pop();
if(tokens[i] == "+")
res = n1 + n2;
else if(tokens[i] == "-")
res = n1 - n2;
else if(tokens[i] == "/")
res = n1 / n2;
else
res = n1 * n2;
numbers.push(res);
}else{
//若为运算数,则直接入栈
numbers.push(tokens[i]);
}
}
return numbers.top();
}
};