栈应用:逆波兰表达式
看完你能手算中缀转后缀、用栈逐图求值并说清每步原因
按 空格/→ 演示下一步
全部页面点击任意一页,跳回舞台从这页播放
栈应用:逆波兰表达式
看完你能手算中缀转后缀、用栈逐图求值并说清每步原因
熟悉的中缀式,麻烦在哪
上一页说了栈能记住「还没轮到的事」。现在拿你最熟悉的算式 3+4×2 开刀:明明一眼能算,为什么计算机处理起来反而要费一番周折?问题就出在我们习以为常的写法上。
口头报「先加盐再炒」要靠听者记顺序,写法里同理要靠规则补全
简化:逆波兰式长什么样
上一页我们看到:中缀式里括号和优先级都是为了约定「先算谁」。如果换一种写法,让运算符紧跟在操作数后面,顺序会不会自己显现出来?看看同一道算式换了位置后长什么样。
步骤卡的「食材、食材、动作」对应逆波兰式的「数、数、运算符」
中缀 vs 后缀
同一个算式,人爱中缀、机爱后缀。容易混:后缀到底好在哪?逐条对照看。
- 运算符夹在两数之间
- 靠括号和优先级消歧义
- 求值需扫描+回看,机器费劲
- 运算符紧跟两数之后
- 无括号,写法本身无歧义
- 一遍扫描,遇算符即弹栈计算
体验:用栈求值的直觉
前页我们看清了后缀式不需要括号,但机器怎么算它?先别想代码,把计算机想成一个端盘子的服务员:手里的托盘就是栈,每个数来了先放上去,直到看到运算符才动手。
新盘子叠在最上面,取用时也先拿最上面的——后进先出对应弹栈顺序
手工求值:一步步演算
拿「3 4 + 2 *」手工演算,逐token扫描,看清栈的每一步变化。
手工转换:中缀变后缀
从左到右扫中缀式,用栈暂存运算符,靠优先级决定何时出栈。
转换中栈的状态图解
这张图按『遇数输出、遇符入栈、出栈有条件』推进,一步步看 9-(2+3) 的转换过程。
自测:后缀式求值
用栈求值后缀式 6 2 3 + -,两个运算符都该先弹谁?正确结果是?
求值算法完整流程
从左到右扫一遍,遇数压栈、遇符弹两个算完再压回,扫完栈顶即答案。
算法代码落地
用栈实现后缀表达式求值,每行对应前面手工演算的一步。
数字入栈、遇运算符弹两个数算完再压回——正是手工演算时栈的变化。
边界与细节辨析
代码写完不等于万事大吉:求值遇上一元负号、转换时栈里堆多少元素、表达式本身不合法,这些边角才是面试与工程里最容易翻车的地方,逐个掰开看。
先放上台的先结(左操作数),最后放的最先被拿走
收束要点
- ✓中缀的麻烦在括号与优先级,后缀天然不需要
- ✓求值与转换共用同一武器:栈暂存待配对的元素
- ✓操作数入栈,运算符弹出两个数算完再压回
- ✓转换时栈里存的是运算符,按优先级决定何时弹出
- ✓细节决定正确性:单目运算、左结合、除零边界
课后思考
先自己琢磨,再对照参考答案——这些问题的价值在思考过程。
参考答案提示:回想手工转换那页。括号和优先级在转换时已被编译进运算次序里——操作数顺序加符号位置就完整表达了结合的先后。
参考答案思考方向:出栈的两个操作数进入寄存器做运算,结果再压回(或留在寄存器)。连续运算可让结果驻留寄存器,减少访存——这正是现代编译器的优化点。
参考答案边界思考:求值顺序隐含在后缀式中,但副作用与运算顺序的约定因语言而异(如 Java、C 对参数求值顺序规定不同),语义需要额外定义。