Appearance
题目
若栈 S1 中保存整数,栈 S2 中保存运算符,函数 F() 依次执行下述各步操作:
1、从 S1 中依次弹出两个操作数 a 和 b;
2、从 S2 中弹出一个运算符 op;
3、执行相应的运算 b op a;
4、将运算结果压入 S1 。
5、假定 S1 中的操作数依次是 5,8,3,2(2 在栈顶),S2 中的运算符依次是 ×,−,+ ( + 在栈顶)。调用 3 次 F() 后,S1 栈顶保存的值是( )。
错因
A
把第 3 步的 b op a 当成了 a op b:先弹出的 a 反而成了左操作数。按这个错误顺序算 2+3=5、5−8=−3、−3×5=−15,结果就是 −15。本质上是没把"先弹出的是右操作数"这一点读进来——这一步是后缀表达式求值的关键约定,反了就全反。
C
通常是两个错误叠加:① 把运算符栈也"读反",认为先弹的是 ×(按入栈顺序的栈底)而不是 +(栈顶);② 又把 b op a 算成 a op b。例如按 a op b 序:2×3=6、6−8=−2、−2+5=3 得不到 −20,但若再把某一步乘法做成 −4×5=−20 之类的错位,就会凑出 −20。无论具体走哪条歧路,根因都是没盯住"栈顶先弹"+"右操作数先弹"这两条规则。
D
和 C 同源,只是中间符号没全错,最后凑成正负相反的 20。常见路径:把运算符栈看反(先用 ×),又坚持 b op a,得到 3×2=6、8−6=2、5+2=7 也凑不出 20;多半是中途某一步把 4×5 当成结果(例如把第二次留下的 −4 与下一个操作数 5 相乘),方向再做反就成了 +20。和 C 一样,问题在于规则没读清。
总解析
题目其实是用两个栈模拟一段后缀表达式求值,关键是抓住两条约定:
- 运算符栈栈顶在最上面(最先弹出的是 +);
- 执行的是
b op a,其中 a 是先弹出的(所以 a 是"右操作数"),b 是后弹出的("左操作数")。
按这两条规则一步步走:
| 调用 | 弹出 a | 弹出 b | 弹出 op | 计算 b op a | 压回 S1 | 调用后 S1(栈底→栈顶) | 调用后 S2 |
|---|---|---|---|---|---|---|---|
| 第 1 次 | 2 | 3 | + | 5 | 5, 8, 5 | ×, − | |
| 第 2 次 | 5 | 8 | − | 3 | 5, 3 | × | |
| 第 3 次 | 3 | 5 | × | 15 | 15 | (空) |
3 次调用后 S1 栈顶就是 15。
直观地讲:表达式实际算的是 ,外层乘法对应栈底的 ×,内层减法对应中间的 −,最里层加法对应最先弹出的 +——栈结构正好对应表达式从外到内的嵌套。
最终答案是 B(15)。