逆波兰表达式求值核心是用std::stack分离数字与运算符:遇数字压栈,遇运算符弹出两操作数(先右后左),用istringstream或stoi按空格切分token以正确处理负数和多位数,除法向零截断,并需检查栈大小和除零。

用 std::stack 处理数字和运算符的分离
逆波兰表达式(后缀表达式)求值的核心是:遇到数字就压栈,遇到运算符就弹出两个操作数——注意顺序,先弹的是右操作数,后弹的是左操作数。C++ 里最直接的方式就是用 std::stack<int></int>,但别直接对字符串逐字符判断:"-123" 是一个数,不是 '-' 加 '123';"10" 是两位数,不能拆成两次入栈。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 用
std::istringstream或循环配合std::stoi按空格切分 tokens,避免手动解析负数或多位数出错 - 对每个 token 判断:
token == "+" || token == "-" || token == "*" || token == "/",其余当作数字处理 - 除法要向零截断(C++ 的
/对整数本就是向零,但注意-5 / 2 == -2,符合题目要求)
处理除零和非法输入的边界情况
题目通常假设输入合法,但真实代码中一旦遇到 "/" 时栈里不足两个数,或第二个弹出的是 0,就会崩溃或算错。不加检查的代码在 OJ 上可能 AC,但本地跑野数据会段错误。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 每次执行运算前,先检查
stack.size() ,触发则抛异常或返回错误码(比如 <code>throw std::runtime_error("invalid expression")) - 遇到
"/"时,取到右操作数后立刻判断是否为0,是则报错——别等做完除法再检查 - 如果输入含非数字非四则符的 token(如
"abc"),std::stoi会抛std::invalid_argument,建议外层 try-catch
std::stack 和手写数组栈的性能差异其实可以忽略
有人担心 std::stack 有额外开销,其实它默认基于 std::deque,但对几百个 token 的表达式,压栈弹栈几十次,耗时远低于 I/O 或字符串分割。真要极致优化,才值得换 std::vector 做容器的手写栈。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 直接用
std::stack<int></int>,别自己封装“更高效”的栈——除非你在嵌入式环境且栈空间严格受限 - 如果用
std::vector手写,记得用back()取顶、pop_back()弹出,别用erase(end()-1),后者是 O(n) - 不需要预先 reserve,逆波兰表达式长度未知,动态增长更稳妥
运算符优先级在这里完全不相关
这是最容易混淆的点:逆波兰表达式本身已消除了括号和优先级问题,求值过程根本不需要考虑 "*" 比 "+" 优先——所有运算都按 token 出现顺序立即执行。如果你在代码里还写了个优先级表或条件分支来“判断该不该算”,说明你没理解后缀表达式的本质。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 见到运算符就无条件弹两个、算一个、压一个,不要加任何“等待更高优先级”逻辑
- 整个过程是纯线性扫描,时间复杂度 O(n),没有回溯、没有递归、不建树
- 测试时用
"4 13 5 / +"(应得 6)和"10 6 9 3 + -11 * / * 17 + 5 +"(应得 22)这种带负数和多层嵌套的样例,比只测"2 1 + 3 *"更能暴露逻辑漏洞
真正卡住人的往往不是算法,而是 token 切分时把 "-1" 当成两个字符,或者除法时忘了右操作数在先弹的那个位置——这两个点,调一次 debugger 就清楚了。










