逆波兰表达式

最近在看算法,看到这个逆波兰表达式,一起学习下:
逆波兰表达式(也称为后缀表达式)是一种数学表达式的书写方式,其中运算符位于操作数之后,无需使用括号即可明确运算顺序。它是**栈(Stack)**的经典应用场景。


📌 核心特点

  1. 运算符在操作数之后

    • 传统表达式(中缀):(2 + 3) * 4
    • 逆波兰表达式(后缀):2 3 + 4 *
  2. 无括号,运算顺序由运算符位置决定

    • 例如:2 3 4 * + 表示 2 + (3 * 4)
  3. 适合用栈计算

    • 遇到数字入栈,遇到运算符弹出栈顶两个数计算,结果再入栈。

📌 与中缀表达式的对比

表达式类型示例运算顺序
中缀表达式3 + 4 * 2需考虑运算符优先级和括号
逆波兰表达式3 4 2 * +严格从左到右计算,无需括号

📌 计算逆波兰表达式的步骤

输入["2", "3", "+", "4", "*"](即 2 3 + 4 *
步骤

  1. 初始化空栈 stack = []
  2. 遍历表达式:
    • "2" → 数字 → 入栈 → stack = [2]
    • "3" → 数字 → 入栈 → stack = [2, 3]
    • "+" → 运算符 → 弹出 32 → 计算 2 + 3 = 5 → 入栈 → stack = [5]
    • "4" → 数字 → 入栈 → stack = [5, 4]
    • "*" → 运算符 → 弹出 45 → 计算 5 * 4 = 20 → 入栈 → stack = [20]
  3. 最终结果:20

📌 代码实现(JavaScript)

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)

📌 中缀表达式转逆波兰表达式

算法步骤(Shunting-yard Algorithm)

  1. 初始化一个输出队列和一个运算符栈。
  2. 遍历中缀表达式:
    • 遇到数字 → 加入输出队列。
    • 遇到运算符 → 弹出栈顶优先级更高或相等的运算符,再入栈。
    • 遇到 ( → 入栈。
    • 遇到 ) → 弹出栈内运算符直到 (
  3. 最后将栈内剩余运算符全部弹出。

示例
中缀表达式:3 + 4 * 2 / (1 - 5)
逆波兰表达式:3 4 2 * 1 5 - / +


📌 逆波兰表达式的优势

  1. 无歧义:无需括号即可明确运算顺序。
  2. 高效计算:只需一次扫描,时间复杂度 O(n)
  3. 适合计算机处理:早期计算器(如HP系列)使用RPN。

📌 常见应用场景

  1. 计算器程序(如HP科学计算器)。
  2. 编译器语法分析(解析算术表达式)。
  3. 算法题(如LeetCode 150. 逆波兰表达式求值)。

📌 总结

关键点说明
定义运算符在操作数之后的表达式
计算方式用栈结构,遇到数字入栈,遇到运算符弹出计算
转换方法Shunting-yard算法(中缀转后缀)
优势无括号、无优先级冲突、计算高效

逆波兰表达式是栈结构的经典应用,理解它对学习编译原理和算法很有帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值