目录
一、三种表达式是什么?
-
中缀表达式(Infix Notation) → 操作符在操作数中间,人类日常使用的写法。 → 例子:
a + (b - c) * d
→ 缺点:计算机需处理优先级和括号,计算复杂。 -
前缀表达式(波兰式,Prefix Notation) → 操作符在操作数之前,形如
+ a * - b c d
。 → 例子:+ a * - b c d
(等价于a + ((b - c) * d)
) → 优点:无需括号,计算机可直接按顺序计算。 -
后缀表达式(逆波兰式,Postfix Notation) → 操作符在操作数之后,形如
a b c - d * +
。 → 例子:a b c - d * +
(等价于a + ((b - c) * d)
) → 优点:计算机计算效率最高,广泛用于编译器和计算器。
二、为什么要转换?
计算机处理中缀表达式需解决两个问题:
-
优先级:
*
和/
优先于+
和-
。 -
括号:括号内的内容优先级最高。 前缀/后缀表达式直接规避了这两个问题,只需按顺序计算!
三、中缀转后缀表达式(重点!)
1. 转换规则
-
操作数(字母/数字)→ 直接输出。
-
操作符(
+ - * /
)→ 与栈顶操作符比较优先级,决定是否弹出(相同优先级相遇若无"("可直接弹出)。 -
括号处理:
-
(
→ 直接压栈(栈内优先级最低)。 -
)
→ 弹出栈顶直到遇到(
,并丢弃括号。
-
-
优先级规则:
操作符 优先级 (
0(最低) +
或-
1 *
或/
2
2. 例子:a + (b - c) * d
→ 后缀表达式
步骤详解:
扫描字符 | 动作 | 输出 | 栈状态 | 规则说明 |
---|---|---|---|---|
a | 输出 | a | [空] | 操作数直接输出 |
+ | 压栈 | a | [+ ] | 栈空,直接压入 |
( | 压栈 | a | [+ , ( ] | 左括号直接压入 |
b | 输出 | a b | [+ , ( ] | 操作数直接输出 |
- | 压栈 | a b | [+ , ( , - ] | 栈顶是 ( ,直接压入(括号内优先级独立) |
c | 输出 | a b c | [+ , ( , - ] | 操作数直接输出 |
) | 弹出 - ,弹出 ( | a b c - | [+ ] | 遇到右括号,弹到左括号 |
* | 压栈 | a b c - | [+ , * ] | * 优先级 > + (栈顶),直接压入 |
d | 输出 | a b c - d | [+ , * ] | 操作数直接输出 |
结束 | 弹出 * ,弹出 + | a b c - d * + | [空] | 扫描完成,弹出栈中剩余操作符 |
最终后缀表达式:a b c - d * +
四、中缀转前缀表达式
1. 转换规则
-
反转中缀表达式:将原表达式从右到左扫描,并反转括号(
(
↔)
)。 -
按后缀转换逻辑处理,得到结果后再反转。
-
优先级规则与后缀转换相同。
2. 例子:a + (b - c) * d
→ 前缀表达式
步骤详解:
-
反转原表达式(注意括号方向): 原式:
a + (b - c) * d
→ 反转后:d * (c - b) + a
(括号内部也反转:(b - c)
→(c - b)
) -
将反转后的表达式转为后缀:
d * (c - b) + a
→ 后缀为d c b - * a +
-
反转后缀结果 → 前缀表达式:
+ a * - b c d
最终前缀表达式:+ a * - b c d
五、三种表达式对比
表达式类型 | 示例 | 计算机计算顺序 | 核心用途 |
---|---|---|---|
中缀 | a + (b - c) * d | 需处理优先级和括号 | 人类书写 |
前缀 | + a * - b c d | 从右到左计算 | 编译器优化、Lisp语法 |
后缀 | a b c - d * + | 从左到右计算 | 计算器、虚拟机指令 |
六、转换口诀总结
-
中缀转后缀:
-
操作数直接走,操作符看栈优先级;左括号压栈不回头,右括号弹出直到空。
-
-
中缀转前缀:
-
反转表达式转后缀,再反转结果得前缀。
-
-
核心原则:
-
高优先级操作符先压栈,括号内优先级独立处理!
-
七、常见问题
-
为什么栈顶是
(
时,操作符可以直接压入? → 因为(
优先级视为最低,括号内的操作符优先级独立于外部。 -
同级操作符(如
+
和-
)如何弹出? → 同级时,先弹出栈顶操作符再压入新的。 -
表达式有多个括号嵌套怎么办? → 每遇到一个
(
就开启一个新的优先级独立区域,按相同规则处理。