最近在看算法,看到这个逆波兰表达式,一起学习下:
逆波兰表达式(也称为后缀表达式)是一种数学表达式的书写方式,其中运算符位于操作数之后,无需使用括号即可明确运算顺序。它是**栈(Stack)**的经典应用场景。
运算符在操作数之后
(2 + 3) * 4
2 3 + 4 *
无括号,运算顺序由运算符位置决定
2 3 4 * +
表示 2 + (3 * 4)
适合用栈计算
表达式类型 | 示例 | 运算顺序 |
---|---|---|
中缀表达式 | 3 + 4 * 2 |
需考虑运算符优先级和括号 |
逆波兰表达式 | 3 4 2 * + |
严格从左到右计算,无需括号 |
输入:["2", "3", "+", "4", "*"]
(即 2 3 + 4 *
)
步骤:
stack = []
"2"
→ 数字 → 入栈 → stack = [2]
"3"
→ 数字 → 入栈 → stack = [2, 3]
"+"
→ 运算符 → 弹出 3
和 2
→ 计算 2 + 3 = 5
→ 入栈 → stack = [5]
"4"
→ 数字 → 入栈 → stack = [5, 4]
"*"
→ 运算符 → 弹出 4
和 5
→ 计算 5 * 4 = 20
→ 入栈 → stack = [20]
20
function evalRPN(tokens) {
const stack = [];
for (const token of tokens) {
if (!isNaN(token)) { // 如果是数字
stack.push(Number(token));
} else { // 如果是运算符
const b = stack.pop();
const a = stack.pop();
switch (token) {
case "+": stack.push(a + b); break;
case "-": stack.push(a - b); break;
case "*": stack.push(a * b); break;
case "/": stack.push(Math.trunc(a / b)); break; // 向零取整
}
}
}
return stack.pop();
}
// 测试
console.log(evalRPN(["2", "3", "+", "4", "*"])); // 输出: 20
console.log(evalRPN(["4", "13", "5", "/", "+"])); // 输出: 6(因为 13 / 5 = 2.6 → 取整 2,4 + 2 = 6)
(
→ 入栈。)
→ 弹出栈内运算符直到 (
。示例:
中缀表达式:3 + 4 * 2 / (1 - 5)
逆波兰表达式:3 4 2 * 1 5 - / +
关键点 | 说明 |
---|---|
定义 | 运算符在操作数之后的表达式 |
计算方式 | 用栈结构,遇到数字入栈,遇到运算符弹出计算 |
转换方法 | Shunting-yard算法(中缀转后缀) |
优势 | 无括号、无优先级冲突、计算高效 |
逆波兰表达式是栈结构的经典应用,理解它对学习编译原理和算法很有帮助!