
AcWing 3302 表达式求值
初始化栈:使用两个栈,一个用于存储运算符(运算符栈),另一个用于存储暂时的数字(数字栈)。 扫描输入表达式:从左到右遍历每个字符,处理数字和运算符。 处理未处理的数字:表达式的最终可能以一个数字结尾,此时需要将其压入数字栈。 处理剩余运算符栈中的运算:扫描结束后,如果运算符栈不为空,继续弹出并计算,直到栈为空。
发布日期:2021-05-28 16:29:37
浏览次数:36
分类:精选文章
本文共 2918 字,大约阅读时间需要 9 分钟。
要解决中缀表达式求值问题,我们可以使用栈的数据结构来帮助处理运算符和数字。以下是详细的解决思路:
问题分析:
给定一个中缀表达式,其中运算符包括加法减法乘法除法,并可能包含括号。表达式的合法性由题目保证,因此我们不需要处理错误情况。目标是从左到右逐步计算表达式,利用栈来维护运算符和目前尚未处理的数字,依次计算表达式的值。
核心思路:
- 处理数字:将连续的数字字符拼接成整数,然后压入数字栈。
- 处理运算符:
- 如果运算符是一个括号,左括号直接压入运算符栈,右括号则处理括号内所有运算。
- 对于加减操作,如果当前运算符的优先级低于栈顶运算符,弹出栈顶运算符并进行计算。
- 对于乘除操作,优先于加减,同样的处理方式。
- 处理右括号:处理括号内的所有运算,直到找到左括号,并弹出左括号,继续处理后续运算。
具体步骤:
初始化:
- 运算符栈和数字栈都初始化为空。
- 设定各运算符的优先级,例如,乘除的优先级高于加减,左括号优先级最低。
扫描字符:
- 对于每个字符,判断是否为数字或运算符:
- 如果是数字,将其暂存到一个变量中,继续扫描下一个字符。如果是运算符,检查之前的数字是否需要入栈处理。
- 如果是运算符,比较栈顶运算符的优先级,决定是否需要计算。
- 处理括号时,改变当前运算符的优先级,确保括号正确闭合。
处理运算符:
- 保持栈中运算符的优先级顺序,确保正确的运算顺序。
- 弹出栈顶的运算符并计算,与当前运算符比较优先级,如优先级低则继续返回。
计算最终结果:
- 扫描完成后,处理未处理的数字和运算符栈中的剩余运算,得到最终结果。
示例分析:
举个例子,表达式为 1+2*3-4/2
:
- 遍历时,遇到1,暂存到数字栈。
- 遇到+,检查栈条件,确定运算符优先级,继续。
- 遇到2,暂存,遇到*,由于的优先级高于栈顶的+,弹出2,计算23=6。
- 接下来扫描到-,弹出栈中的议,处理后续运算。
代码实现:
以下是一个可能的C++实现,将其余部分的代码块化为函数:
#include#include using namespace std;stack numStack;stack opStack;string s;// 定义运算符优先级:lower表示低于,higher表示高于bool cmp(char c1, char c2) { if (c1 == '(' || c2 == '(') return false; if (c1 == '+' || c1 == '-') { return c2 != '*' && c2 != '/'; } else if (c1 == '*' || c1 == '/') { return c2 == '*' || c2 == '/'; } return false;}void compute() { int a = numStack.top(); numStack.pop(); int b = numStack.top(); numStack.pop(); char c = opStack.top(); opStack.pop(); if (c == '+') { numStack.push(a + b); } else if (c == '-') { numStack.push(b - a); } else if (c == '*') { numStack.push(a * b); } else if (c == '/') { if (b > 0) { int result = b / a; numStack.push(result); } else { // 处理负数取整 numStack.push((b - 1) / a + 1); } }}int main() { cin >> s; int n = 0; for (int i = 0; i < s.size(); i++) { if (isdigit(s[i])) { n = n * 10 + (s[i] - '0'); } else { // 处理数字 if (i > 0 && isdigit(s[i-1])) { numStack.push(n); n = 0; } // 处理运算符或括号 if (s[i] == '(') { opStack.push(s[i]); } else if (s[i] == ')') { while (opStack.top() != '(') { compute(); } opStack.pop(); // 消除左括号 } else { // 遇到运算符,开始处理 while (!opStack.empty() && cmp(s[i], opStack.top())) { compute(); } opStack.push(s[i]); } } } // 处理剩下的数字 if (n != 0) { numStack.push(n); } // 计算完罢了所有运算符 while (!opStack.empty()) { compute(); } cout << numStack.top();}
总结:
通过实现上述逻辑,我们能够正确地处理中缀表达式,计算出其值。代码中详细处理了括号运算、运算符的优先级以及取整规则,确保结果正确。
发表评论
最新留言
做的很好,不错不错
[***.243.131.199]2025年04月20日 04时54分49秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
推荐几篇近期必看的视觉综述,含GAN、Transformer、人脸超分辨、遥感等
2021-05-12
BUU-MISC-caesar
2021-05-12
【专题3:电子工程师 之 上位机】 之 【46.QT音频接口】
2021-05-12
一文理解设计模式--命令模式(Command)
2021-05-12
VTK:可视化之RandomProbe
2021-05-12
block多队列分析 - 2. block多队列的初始化
2021-05-12
Java时间
2021-05-12
不编译只打包system或者vendor image命令
2021-05-12
【编程】C语言入门:1到 100 的所有整数中出现多少个数字9
2021-05-12
flink启动(二)
2021-05-12
pair的用法
2021-05-12
Flex 布局的自适应子项内容过长导致其被撑大问题
2021-05-12
PL/SQL 动态Sql拼接where条件
2021-05-12
Lua-table 一种更少访问的安全取值方式
2021-05-12
虚函数
2021-05-12
【自学Flutter】4.1 Material Design字体图标的使用(icon)
2021-05-12
【换行符】什么时候用cin.get()吃掉输入流中的换行符
2021-05-12
【二叉树】已知后序与中序求先序
2021-05-12