栈的应用:中缀,后缀,前缀表达式的相互转换,及利用后缀表达式求值

裸题: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();
    }
};
中缀式转换为后缀式
  1. 从左向右开始扫描中缀表达式;

  2. 遇到数字加入到后缀表达式之中(从左往右生成)

  3. 遇到运算符时:
    a. 若为 ‘(’ ,入栈
    b. 若为 ‘)’ ,则依次把栈中的运算符加入后缀表达式中,直到出现 ‘(’ ,从栈中删除 ‘(’ 。
    c. 若为除括号外的其他运算符,当其优先级高于或等于除 ‘(’ 以外的栈顶运算符时,直接入栈(当栈顶元素为左括号时,运算符直接入栈)。否则从栈顶开始,依次弹出比当前处理的运算符优先级高优先级相等的运算符,直到一个比它优先级低的或遇到一个左括号时停止出栈。

  4. 当扫描的中缀表达式结束时,栈中的所有运算符一次出栈加入到后缀表达式中。

中缀式转换为前缀式
  1. 从右向左开始扫描中缀表达式;

  2. 遇到数字加入到前缀表达式之中(从右往左生成)

  3. 遇到运算符时:
    a. 若为 ‘)’ ,入栈
    b. 若为 ‘(’ ,则依次把栈中的运算符加入前缀表达式中,直到出现 ‘)’ ,从栈中删除 ‘)’ 。
    c. 若为除括号外的其他运算符,当其优先级高于或等于除 ‘)’ 以外的栈顶运算符时,直接入栈(当栈顶元素为右括号时,运算符直接入栈)。否则从栈顶开始,依次弹出比当前处理的运算符优先级高的运算符,直到一个比它优先级高或等于的或遇到一个右括号时停止出栈。

  4. 当扫描的中缀表达式结束时,栈中的所有运算符一次出栈加入到前缀表达式中。

后缀式转换为前缀式
  1. 从左向右扫描后缀表达式,遇到数字就进栈。
  2. 遇到运算符,从栈中弹出两个元素,第一个弹出的元素放到第二个弹出的元素的右面,并将运算符放到第二个弹出元素的左边,将结果串压入栈中
  3. 重复1,2
利用后缀表达式求值(遇到数字就入栈,遇到运算符就运算)
  1. 从左向右依次扫描后缀表达式
  2. 当遇到数字时将其压入栈中,当遇到运算符时,从栈中弹出两个数字,第一个弹出的数字在右,第二个弹出的数字在左,进行运算后将结果压入栈中。
  3. 重复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];
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
不好意思,我看到你的问题是一样的,我之前回答的是解决中缀表达式后缀表达式的问题,如果你想了解如何用解决中缀表达式前缀表达式,可以参考以下思路: 1. 将中缀表达式倒序。 2. 将倒序后的中缀表达式中的左右括号互换。 3. 从右往左遍历倒序后的中缀表达式的每个元素。 4. 如果遇到操作数,直接输出。 5. 如果遇到右括号或运算符,将其压入中。 6. 如果遇到左括号,将中的元素依次弹出并输出,直到遇到右括号或运算符为止。将弹出的元素倒序输出。 7. 遍历完倒序后的中缀表达式后,将中剩余的元素依次弹出并输出。 8. 将输出的前缀表达式倒序即为原始中缀表达式前缀表达式。 代码实现如下: ```c++ #include <iostream> #include <stack> #include <algorithm> using namespace std; int priority(char c) // 定义运算符优先级 { if (c == '+' || c == '-') return 1; if (c == '*' || c == '/') return 2; return 0; } void infixToPrefix(string infix) // 中缀表达式前缀表达式 { reverse(infix.begin(), infix.end()); // 将中缀表达式倒序 stack<char> s; for (int i = 0; i < infix.length(); i++) { char c = infix[i]; if (isdigit(c)) cout << c; // 遇到操作数 else if (c == ')') s.push(c); // 遇到右括号 else if (c == '(') { // 遇到左括号 while (!s.empty() && s.top() != ')') { cout << s.top(); s.pop(); } s.pop(); // 弹出右括号 } else { // 遇到运算符 while (!s.empty() && priority(s.top()) >= priority(c)) { cout << s.top(); s.pop(); } s.push(c); } } while (!s.empty()) { // 将中剩余元素输出 cout << s.top(); s.pop(); } reverse(infix.begin(), infix.end()); // 将输出的前缀表达式倒序 } int main() { string infix = "1+2*(3-4)/5"; infixToPrefix(infix); return 0; } ``` 输出结果为:`+/1/*2-345`,即为转换后的前缀表达式

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值