Files
python/TangDou/CSP-J/J1_2022/表达式转换与表达式求值.md
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

6.5 KiB
Raw Blame History

题目传送门

第四题还没看

表达式转换与表达式求值

一、四则运算

中缀转后缀

/*
比如:
a+b*c+(d*e+f)*g

应输出:
abc*+de*f+g*+
*/
#include <iostream>
#include <cstring>
#include <stack>
#include <unordered_map>

using namespace std;

unordered_map<char, int> h{{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}, {'(', 0}};
string infix;   //输入的中缀表达式
string postfix; //后缀的结果表达式
stack<char> s;  //使用到的操作符+数字栈,这里的数字不用真的计算,所以统一按字符处理

int main() {
    cin >> infix;
    for (int i = 0; i < infix.size(); i++) {
        //是数字或字母的情况,直接记录到后缀表达式中
        if (isdigit(infix[i]) || (infix[i] >= 'a' && infix[i] <= 'z'))
            postfix += infix[i];
        else {
            //① 栈为空时直接入栈
            if (s.empty()) s.push(infix[i]);
            //② 左括号入栈
            else if (infix[i] == '(')
                s.push(infix[i]);
            //③ 如果是右括号,就在栈中不断弹出操作符和数字,直到栈顶是(为止
            else if (infix[i] == ')') {
                while (s.top() != '(') {
                    postfix += s.top();
                    s.pop();
                }
                //弹出左括号,但不输出
                s.pop();
            } else {
                //④栈顶元素的优先级大于等于当前的运算符,就将其输出
                while (s.size() && h[infix[i]] <= h[s.top()]) {
                    postfix += s.top();
                    s.pop();
                }
                //⑤当前运算符入栈
                s.push(infix[i]);
            }
        }
    }
    //⑥ 如果不为空,就把所有的元素全部弹出
    while (s.size()) {
        postfix += s.top();
        s.pop();
    }
    //输出后缀表达式
    cout << postfix << endl;
    return 0;
}

后缀表达式求值

#include <iostream>
#include <stack>
#include <string>
#include <unordered_map>
//下面的代码实现了由中缀表达式求值的过程
using namespace std;

/*
测试用例I:
(2+2)*(1+1)

答案:8

测试用例II:
2+(3*4)-((5*9-5)/8-4)

答案:13

*/

stack<int> num; //数字栈
stack<char> op; //操作符栈

//优先级表
unordered_map<char, int> h{{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}, {'(', 0}};

/**
 * 功能:计算两个数的和差积商
 */
void eval() {
    int a = num.top(); //第二个操作数
    num.pop();

    int b = num.top(); //第一个操作数
    num.pop();

    char p = op.top(); //运算符
    op.pop();

    int r = 0; //结果
    //计算结果
    if (p == '+')
        r = b + a;
    else if (p == '-')
        r = b - a;
    else if (p == '*')
        r = b * a;
    else if (p == '/')
        r = b / a;
    //结果入栈
    num.push(r);
}

int main() {
    //读入表达式
    string s;
    cin >> s;
    //遍历字符串的每一位
    for (int i = 0; i < s.size(); i++) {
        //① 如果是数字,则入栈
        if (isdigit(s[i])) {
            //读出完整的数字
            int x = 0;
            while (i < s.size() && isdigit(s[i])) {
                x = x * 10 + s[i] - '0';
                i++;
            }
            i--; //加多了一位,需要减去

            num.push(x); //数字入栈
        }
        //② 左括号无优先级,入栈
        else if (s[i] == '(')
            op.push(s[i]);
        //③ 右括号时,需计算最近一对括号里面的值
        else if (s[i] == ')') {
            //从栈中向前找,一直找到左括号
            while (op.top() != '(') eval(); //将左右括号之间的计算完,维护回栈里
            //左括号出栈
            op.pop();
        } else { //④ 运算符
            //如果待入栈运算符优先级低,则先计算
            while (op.size() && h[op.top()] >= h[s[i]]) eval();
            op.push(s[i]); //操作符入栈
        }
    }
    while (op.size()) eval(); //⑤ 剩余的进行计算

    printf("%d\n", num.top()); //输出结果
    return 0;
}

二、逻辑运算

中缀转后缀

//下面的代码实现了中缀的逻辑表达式 转 后缀的逻辑表达式
#include <iostream>
#include <cstring>
#include <stack>
#include <unordered_map>

using namespace std;
/*
测试用例:
0&(0|1|0)

答案:
001|0|&
*/
unordered_map<char, int> h{{'|', 1}, {'&', 2}, {'(', 0}};
string infix;   //输入的中缀表达式
string postfix; //后缀的结果表达式
stack<char> s;  //使用到的操作符+数字栈,这里的数字不用真的计算,所以统一按字符处理

int main() {
    cin >> infix;
    for (int i = 0; i < infix.size(); i++) {
        //是数字或字母的情况,直接记录到后缀表达式中
        if (isdigit(infix[i]) || (infix[i] >= 'a' && infix[i] <= 'z'))
            postfix += infix[i];
        else {
            //① 栈为空时直接入栈
            if (s.empty()) s.push(infix[i]);
            //② 左括号入栈
            else if (infix[i] == '(')
                s.push(infix[i]);
            //③ 如果是右括号,就在栈中不断弹出操作符和数字,直到栈顶是(为止
            else if (infix[i] == ')') {
                while (s.top() != '(') {
                    postfix += s.top();
                    s.pop();
                }
                //弹出左括号,但不输出
                s.pop();
            } else {
                //④栈顶元素的优先级大于等于当前的运算符,就将其输出
                while (s.size() && h[infix[i]] <= h[s.top()]) {
                    postfix += s.top();
                    s.pop();
                }
                //⑤当前运算符入栈
                s.push(infix[i]);
            }
        }
    }
    //⑥ 如果不为空,就把所有的元素全部弹出
    while (s.size()) {
        postfix += s.top();
        s.pop();
    }
    //输出后缀表达式
    cout << postfix << endl;
    return 0;
}

后缀表达式求值

(1,a_1,b_1) | (?,a_2,b_2) \Rightarrow (1,a_1,b_1+1)

(0,a_1,b_1) | (?,a_2,b_2) \Rightarrow (?,a_1+a_2,b_1+b_2)

(1,a_1,b_1) \& (?,a_2,b_2) \Rightarrow (?,a_1+a_2,b_1+b_2)

(0,a_1,b_1) \& (?,a_2,b_2) \Rightarrow (0,a_1+1,b_1)