裸题:BM49 表达式求值利用中缀转后缀,后缀求值思路
// 代码已ac
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 返回表达式的值
* @param s string字符串 待计算的表达式
* @return int整型
*/
int solve(string s) {
// 中缀转后缀,后缀进行求值
vector<string> data = to_houzhui(s);
for(auto str : data){
cout << str << " ";
}
cout << endl;
return houzhui_to_value(data);
}
// 中缀转后缀
/*
思路:
遇到数字就将数字添加到字符串中
// 运算压栈与弹栈规则
压栈规则:
1. 如果是(, 直接压栈
2. 如果栈顶元素为+或-,运算符直接压栈(**大于等于**当前栈顶优先级的运算符直接压栈)
弹栈规则:
1. 如果是), 弹出所有(之前的元素
2. 如果当前栈顶元素优先级大于当前待压栈运算符,弹栈(弹出比当前待压栈运算符优先级**大于等于**的运算符)
*/
vector<string> to_houzhui(string str){
int index = 0, size = str.size();
stack<char> stack_symbol;
vector<string> ans;
while(index < size){
char ch = str[index];
if(ch == '(' || ch == '*' || ch == '/'){ // 优先较高的
stack_symbol.push(ch);
++index;
}else if(ch == ')') { // 不断弹出符号栈,直到遇到'('
while(!stack_symbol.empty() && stack_symbol.top() != '('){
ans.push_back(string(1, stack_symbol.top()));
stack_symbol.pop();
}
stack_symbol.pop();
++index;
}else if(ch >= '0' && ch <= '9'){
int sum = 0;
do{
sum = sum * 10 + str[index] - '0';
++index;
}while(str[index] >= '0' && str[index] <= '9');
ans.push_back(to_string(sum));
}else{ // ch == '-'或'+' 弹栈
while(!stack_symbol.empty() &&
(stack_symbol.top() == '*' || stack_symbol.top() == '/' || stack_symbol.top() == '+' || stack_symbol.top() == '-') && // 优先级大于等于+,-运算符
(ch == '+' || ch == '-')){
ans.push_back(string(1, stack_symbol.top()));
stack_symbol.pop();
}
stack_symbol.push(ch);
++index;
}
}
while(!stack_symbol.empty()){
ans.push_back(string(1, stack_symbol.top()));
stack_symbol.pop();
}
return ans;
}
// 后缀求值
int houzhui_to_value(vector<string> data){
stack<int> stack_num;
int size = data.size(), index = 0;
while(index < size){
string str = data[index];
if(str == "+" || str == "-" || str == "*" || str == "/"){ // 遇到符号就运算
int a = stack_num.top();
stack_num.pop();
if(str == "+"){
stack_num.top() += a;
}else if(str == "-"){
stack_num.top() -= a;
}else if(str == "*"){
stack_num.top() *= a;
}else{
stack_num.top() /= a;
}
}else{
stack_num.push(stoi(str));
}
++index;
}
return stack_num.top();
}
};
中缀式转换为后缀式
-
从左向右开始扫描中缀表达式;
-
遇到数字加入到后缀表达式之中(从左往右生成)
-
遇到运算符时:
a. 若为 ‘(’ ,入栈
b. 若为 ‘)’ ,则依次把栈中的运算符加入后缀表达式中,直到出现 ‘(’ ,从栈中删除 ‘(’ 。
c. 若为除括号外的其他运算符,当其优先级高于或等于除 ‘(’ 以外的栈顶运算符时,直接入栈(当栈顶元素为左括号时,运算符直接入栈)。否则从栈顶开始,依次弹出比当前处理的运算符优先级高和优先级相等的运算符,直到一个比它优先级低的或遇到一个左括号时停止出栈。 -
当扫描的中缀表达式结束时,栈中的所有运算符一次出栈加入到后缀表达式中。
中缀式转换为前缀式
-
从右向左开始扫描中缀表达式;
-
遇到数字加入到前缀表达式之中(从右往左生成)
-
遇到运算符时:
a. 若为 ‘)’ ,入栈
b. 若为 ‘(’ ,则依次把栈中的运算符加入前缀表达式中,直到出现 ‘)’ ,从栈中删除 ‘)’ 。
c. 若为除括号外的其他运算符,当其优先级高于或等于除 ‘)’ 以外的栈顶运算符时,直接入栈(当栈顶元素为右括号时,运算符直接入栈)。否则从栈顶开始,依次弹出比当前处理的运算符优先级高的运算符,直到一个比它优先级高或等于的或遇到一个右括号时停止出栈。 -
当扫描的中缀表达式结束时,栈中的所有运算符一次出栈加入到前缀表达式中。
后缀式转换为前缀式
- 从左向右扫描后缀表达式,遇到数字就进栈。
- 遇到运算符,从栈中弹出两个元素,第一个弹出的元素放到第二个弹出的元素的右面,并将运算符放到第二个弹出元素的左边,将结果串压入栈中
- 重复1,2
利用后缀表达式求值(遇到数字就入栈,遇到运算符就运算)
- 从左向右依次扫描后缀表达式
- 当遇到数字时将其压入栈中,当遇到运算符时,从栈中弹出两个数字,第一个弹出的数字在右,第二个弹出的数字在左,进行运算后将结果压入栈中。
- 重复1,2
// cpp version 见文首
int Get_res(char *str) {
char *p = str;
int stack[N];
int top = -1,m,n;
while (*p != '#') {
if (*p == '+') {
n = stack[top--];
m = stack[top--];
stack[++top] = m + n;
}
else if (*p == '-') {
n = stack[top--];
m = stack[top--];
stack[++top] = m - n;
}
else if (*p == '*') {
n = stack[top--];
m = stack[top--];
stack[++top] = m * n;
}
else if (*p == '/') {
n = stack[top--];
m = stack[top--];
stack[++top] = m / n;
}
else {
stack[++top] = *p - '0';
}
p++;
}
return stack[top];
}