CSP-201903-2-二十四点

CSP-201903-2-二十四点

一、中缀表达式转后缀表达式

中缀表达式是一种常见的数学表达式书写方式,其中操作符位于相关的操作数之间,如 A + B。而后缀表达式(逆波兰表示法)则是一种没有括号,操作符跟随操作数之后的表示方法,例如相同的表达式在后缀表示法中写作 A B +

转换过程通常使用一个栈来临时存储操作符,以保持操作符的正确顺序和处理优先级。以下是转换步骤:

  1. 创建一个空栈用于存放操作符,创建一个空列表用于输出后缀表达式。
  2. 从左到右扫描中缀表达式
    • 如果遇到操作数,则直接将其加到输出列表。
    • 如果遇到左括号 (,则将其压入栈中。
    • 如果遇到右括号 ),则从栈中弹出操作符并加到输出列表,直到遇到左括号为止(左括号弹出栈但不加到输出列表)。
    • 如果遇到操作符,则:
      • 从栈中弹出所有优先级大于或等于当前操作符的操作符,并将它们加到输出列表。
      • 然后将当前操作符压入栈中。
  3. 扫描完毕后,将栈中剩余的操作符依次弹出并加到输出列表的末尾。
  4. 最终,输出列表就是转换得到的后缀表达式。

二、计算后缀表达式的结果

计算后缀表达式(逆波兰表示法)的结果也需要使用一个栈。以下是计算步骤:

  1. 创建一个空栈用于存放操作数。
  2. 从左到右扫描后缀表达式
    • 如果遇到操作数,则将其压入栈中。
    • 如果遇到操作符,则从栈中弹出顶部的两个操作数(注意弹出的顺序),对它们应用操作符进行计算,然后将结果压回栈中。
  3. 重复上述过程,直到后缀表达式的末端。
  4. 表达式结束时,栈顶的元素即为整个表达式的计算结果。

三、举例

例子1:

中缀表达式: 3 + 4 * 2 / ( 1 - 5 )

后缀表达式: 3 4 2 * 1 5 - / +

例子2:

中缀表达式: (( 7 + 3 ) * ( 5 - 2 )) / ( 8 - 4 )

后缀表达式: 7 3 + 5 2 - * 8 4 - /

例子3:

中缀表达式: 8 + 3 * 4 / 2

后缀表达式: 8 3 4 * 2 / +

四、代码

#include <iostream>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <cctype>

using namespace std;

// 检查是否为操作符
bool isOperator(char c) {
    return c == '+' || c == '-' || c == 'x' || c == '/';
}

// 比较操作符优先级
int precedence(char op) {
    if (op == '+' || op == '-') return 1;
    if (op == 'x' || op == '/') return 2;
    return 0;
}

// 中缀表达式转后缀表达式
string infixToPostfix(const string& infix) {
    stack<char> opStack;
    string postfix;
    for (char c : infix) {
        if (isdigit(c)) {
            postfix += c;
        }
        else if (c == '(') {
            opStack.push(c);
        }
        else if (c == ')') {
            while (!opStack.empty() && opStack.top() != '(') {
                postfix += opStack.top();
                opStack.pop();
            }
            opStack.pop(); // 弹出 '('
        }
        else if (isOperator(c)) {
            while (!opStack.empty() && precedence(opStack.top()) >= precedence(c)) {
                postfix += opStack.top();
                opStack.pop();
            }
            opStack.push(c);
        }
    }
    while (!opStack.empty()) {
        postfix += opStack.top();
        opStack.pop();
    }
    return postfix;
}

// 计算后缀表达式
int evaluatePostfix(const string& postfix) {
    stack<int> valStack;
    for (char c : postfix) {
        if (isdigit(c)) {
            valStack.push(c - '0');
        }
        else {
            int val2 = valStack.top(); valStack.pop();
            int val1 = valStack.top(); valStack.pop();
            switch (c) {
            case '+': valStack.push(val1 + val2); break;
            case '-': valStack.push(val1 - val2); break;
            case 'x': valStack.push(val1 * val2); break;
            case '/': valStack.push(val1 / val2); break;
            }
        }
    }
    return valStack.top();
}

int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        string infix;
        cin >> infix;
        string postfix = infixToPostfix(infix);
        int result = evaluatePostfix(postfix);
        if (result == 24)
        {
            cout << "Yes\n";
        }
        else
        {
            cout << "No\n";
        }
    }
    return 0;
}

请添加图片描述

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值