[题目传送门](https://www.bilibili.com/video/BV1EG4y1h7P1) 第四题还没看 ## 表达式转换与表达式求值 ### 一、四则运算 #### 中缀转后缀 ```c++ /* 比如: a+b*c+(d*e+f)*g 应输出: abc*+de*f+g*+ */ #include #include #include #include using namespace std; unordered_map h{{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}, {'(', 0}}; string infix; //输入的中缀表达式 string postfix; //后缀的结果表达式 stack 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; } ``` #### 后缀表达式求值 ```c++ #include #include #include #include //下面的代码实现了由中缀表达式求值的过程 using namespace std; /* 测试用例I: (2+2)*(1+1) 答案:8 测试用例II: 2+(3*4)-((5*9-5)/8-4) 答案:13 */ stack num; //数字栈 stack op; //操作符栈 //优先级表 unordered_map 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; } ``` ### 二、逻辑运算 #### 中缀转后缀 ```c++ //下面的代码实现了中缀的逻辑表达式 转 后缀的逻辑表达式 #include #include #include #include using namespace std; /* 测试用例: 0&(0|1|0) 答案: 001|0|& */ unordered_map h{{'|', 1}, {'&', 2}, {'(', 0}}; string infix; //输入的中缀表达式 string postfix; //后缀的结果表达式 stack 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)$