中缀表达式转换到后缀表达式

求一个可能包含加、减、乘、除、乘方运算的中缀表达式的值。

在计算机中,我们常用栈来解决这一问题。首先将中缀表达式转换到后缀表达式,然后对后缀表达式求值。

加、减、乘、除、乘方分别用+,-,*, /, ^来表示。表达式可以有圆括号()。

时间限制:1000
内存限制:65536
输入
第一行为测试数据的组数N。 接下来的N行,每行是一个中缀表达式。 每个表达式中,圆括号、运算符和运算数相互之间都用空格分隔,运算数是整数。一般运算数可正可负(负数的符号和数字之间无空格),指数一定为自然数(0和正整数)。不必考虑除0的情况。每个运算数均可由int放下。不必考虑溢出。中缀表达式的字符串长度不超过600。乘方的优先级比乘除都高,结合性是向左结合,如2 ^ 3 ^ 4表示( 2 ^ 3 ) ^ 4 = 4096。除法的商向下取整。
输出
对每一组测试数据输出一行,为表达式的值
样例输入
2
31 * ( 5 - ( -3 + 25 ) ) + 70 ^ 2
2 * 5 + 6 * ( 7 - 8 ) + 6
样例输出
4373
10


#include <iostream>
#include <stack>
#include <string>
#include <cmath>
using namespace std;

// 定义运算符优先级函数
int youxiancixu(char op) {
    if (op == '+' || op == '-')
        return 1;
    if (op == '*' || op == '/')
        return 2;
    if (op == '^')
        return 3;
    return 0;
}

// 定义运算函数
int yunsuan(int a, int b, char op) {
    switch (op) {
        case '+':
            return a + b;
        case '-':
            return a - b;
        case '*':
            return a * b;
        case '/':
            return a / b;
        case '^':
            return pow(a, b);
    }
    return 0;
}

// 定义表达式求值函数
int evaluateExpression(string x) {
    stack<int> operandStack; // 操作数栈
    stack<char> operatorStack; // 运算符栈
    
    for (char& c : x) {
        if (c == ' ')
            continue;
        
        if (isdigit(c)) { // 如果是数字则入栈到操作数栈
            operandStack.push(c - '0');
        } else if (c == '(') { // 如果是左括号则入栈到运算符栈
            operatorStack.push(c);
        } else if (c == ')') { // 如果是右括号,则将栈内运算符进行计算,直到遇到左括号
            while (!operatorStack.empty() && operatorStack.top() != '(') {
                int b = operandStack.top();
                operandStack.pop();
                
                int a = operandStack.top();
                operandStack.pop();
                
                char op = operatorStack.top();
                operatorStack.pop();
                
                int result = yunsuan(a, b, op);
                operandStack.push(result);
            }
            
            if (!operatorStack.empty() && operatorStack.top() == '(') {
                operatorStack.pop(); // 弹出左括号
            }
        } else { // 如果是运算符
            // 将栈内优先级高于或等于当前运算符的运算符进行计算,直到遇到优先级更低的运算符或左括号
            while (!operatorStack.empty() && youxiancixu(c) <= youxiancixu(operatorStack.top())) {
                int b = operandStack.top();
                operandStack.pop();
                
                int a = operandStack.top();
                operandStack.pop();
                
                char op = operatorStack.top();
                operatorStack.pop();
                
                int result = yunsuan(a, b, op);
                operandStack.push(result);
            }
            
            operatorStack.push(c); // 当前运算符入栈
        }
    }
    
    // 清空栈内剩余的运算符进行计算
    while (!operatorStack.empty()) {
        int b = operandStack.top();
        operandStack.pop();
        
        int a = operandStack.top();
        operandStack.pop();
        
        char op = operatorStack.top();
        operatorStack.pop();
        
        int result = yunsuan(a, b, op);
        operandStack.push(result);
    }
    
    return operandStack.top(); // 返回最终计算结果
}

int main() {
    int n;
    
    if (cin >> n) { // 输入要执行的循环次数
        cin.get(); // 读取掉回车符
        
        for (int i = 1; i <= n; i++) {
            string x;
            getline(cin, x); // 读取表达式
            
            int result = evaluateExpression(x); // 求值
            cout << result << endl; // 输出结果
        }
    }
    
    return 0;
}

【以下回答由 GPT 生成】

解决方案

  1. 首先我们需要定义一个函数,用于判断字符是数字还是运算符。这个函数接收一个字符作为参数,返回一个布尔值。如果字符是数字,则返回True,否则返回False。
def is_number(char):
    return char.isdigit()
  1. 接下来,我们定义一个函数,用于判断运算符的优先级。这个函数接收一个运算符作为参数,返回一个整数,表示优先级。优先级越高的运算符,返回的整数值越大。
def precedence(operator):
    if operator == '^':
        return 3
    elif operator == '*' or operator == '/':
        return 2
    elif operator == '+' or operator == '-':
        return 1
    else:
        return 0
  1. 然后,我们定义一个函数,用于将中缀表达式转换为后缀表达式。这个函数接收一个中缀表达式作为参数,返回一个后缀表达式。我们可以使用栈来实现这个转换过程。具体步骤如下:
  2. 创建一个空栈和一个空列表,用于存储后缀表达式。
  3. 遍历中缀表达式的每个字符:
    • 如果字符是数字,则直接加入后缀表达式列表。
    • 如果字符是左括号,则将其压入栈。
    • 如果字符是右括号,则将栈中的运算符依次弹出,加入后缀表达式列表,直到遇到左括号为止。然后将左括号弹出栈。
    • 如果字符是运算符:
    • 将栈中优先级较高的运算符弹出,加入后缀表达式列表,直到栈为空或栈顶的运算符优先级比当前运算符低。然后将当前运算符压入栈。
  4. 循环结束后,如果栈中还有运算符,则将其依次弹出,加入后缀表达式列表。
  5. 返回后缀表达式列表。
def infix_to_postfix(infix_expr):
    stack = []
    postfix = []
    operators = ['+', '-', '*', '/', '^']
    for char in infix_expr.split():
        if is_number(char):
            postfix.append(char)
        elif char == '(':
            stack.append(char)
        elif char == ')':
            while stack and stack[-1] != '(':
                postfix.append(stack.pop())
            stack.pop()
        elif char in operators:
            while stack and precedence(stack[-1]) >= precedence(char):
                postfix.append(stack.pop())
            stack.append(char)
    while stack:
        postfix.append(stack.pop())
    return ' '.join(postfix)
  1. 最后,我们定义一个函数,用于计算后缀表达式的值。这个函数接收一个后缀表达式作为参数,返回一个整数,表示计算结果。我们也可以使用栈来实现这个计算过程。具体步骤如下:
  2. 创建一个空栈。
  3. 遍历后缀表达式的每个字符:
    • 如果字符是数字,则将其转换为整数,并压入栈。
    • 如果字符是运算符,则从栈中弹出两个数字,进行相应的运算,并将运算结果压入栈。
  4. 循环结束后,栈中只会剩下一个数字,即为计算结果。
  5. 返回栈中剩下的数字。
def evaluate_postfix(postfix_expr):
    stack = []
    operators = ['+', '-', '*', '/', '^']
    for char in postfix_expr.split():
        if is_number(char):
            stack.append(int(char))
        elif char in operators:
            num2 = stack.pop()
            num1 = stack.pop()
            if char == '+':
                stack.append(num1 + num2)
            elif char == '-':
                stack.append(num1 - num2)
            elif char == '*':
                stack.append(num1 * num2)
            elif char == '/':
                stack.append(num1 // num2)
            elif char == '^':
                stack.append(num1 ** num2)
    return stack.pop()
  1. 最后,我们通过循环读取输入,并调用上述函数来解决多组测试数据的求值问题。
while True:
    try:
        expr = input()
        postfix_expr = infix_to_postfix(expr)
        result = evaluate_postfix(postfix_expr)
        print(result)
    except EOFError:
        break

这样,我们就完成了中缀表达式转换到后缀表达式求值的问题。请注意,由于输入多组测试数据,我们通过捕获EOFError异常来判断输入是否结束。



【相关推荐】



如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^