计算逆波兰式(后缀表达式)的值

本文详细介绍了逆波兰表达式(后缀表达式)的概念,对比中缀表达式,阐述了其转换方法及计算原理。通过具体实例,展示了如何将中缀表达式转换为后缀表达式,并提供了一段Java代码实现逆波兰表达式的计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

运算符仅包含"+","-","*“和”/",被操作数可能是整数或其他表达式

例如:

[“2”, “1”, “+”, “3”, “*”] -> ((2 + 1) * 3) -> 9↵ [“4”, “13”, “5”, “/”, “+”] -> (4 + (13 / 5)) -> 6

介绍相关知识:什么是逆波兰式(后缀表达式)

逆波兰表达式又叫后缀表达式,中学时候学的那种表达式叫中缀表达式。

例如,5×(6+3)÷3-1 , 3×(4÷(2+1)×2)-3

例子中的这两个式子,就是中缀表达式。下面这两个就是后缀表达式:

563+×3÷1- , 3421+÷2××3-

中缀表达式变后缀表达式方法:

见到数字直接输出,见到符号按一定规则入栈出栈。

规则就是,用当前的符号与栈顶的符号比较优先级,如果当前符号优先级小于栈顶符号的优先级,则把栈里面的符号都弹出来。括号的操作除外,括号是左括号优先级最高,不管跟啥比,都是入栈;右括号是优先级最低,跟啥比都是弹出栈内符号,但只弹到跟它匹配的最近的那个左括号。

这里就涉及到一个符号优先级的问题。看下图吧,从上往下的符号是优先级从高到低。

在这里插入图片描述

这样就可以开始说怎么互相转换了。上面的两个例子式子都说一说:

5×(6+3)÷3-1

先看到的是5,直接输出,现在的后缀表达式为:“5”。下一个,“×”,压入栈中。下一个,“(”,优先级超级高,处在金字塔顶端的符号,也压入栈中。下一个,“6”,数字,直接输出,现在的后缀表达式为:“56”。目前状况看下图吧。
在这里插入图片描述

下一个, “+” ,当栈顶是 “(” 的时候,当前的符号优先级是一定小于 “(” 的,但不能还按照原来的规则,把栈内符号弹出。 “(” 的弹出条件是等到与之匹配的最近的 “)” 。只有等到了 “)” , “(” 才弹出。当然了, “(” 和 “)” 中间一定还会有别的运算符,弹的时候一起都弹出来。而且当遇到 “)” 的时候,不是全栈都弹出来,而是弹到 “(” 停止。那么,再说回来,当前符号是 “+” ,由于 “(” 只等到 “)” 才弹出,所以把 “+” 压入栈中。下一个, “3” ,直接输出。目前的状况看下图。

在这里插入图片描述

下一个, “)” ,这个优先级极低,所以弹出栈中元素,但这个也不能按常规的规则操作。遇到 “)” 了,不应把全栈都弹出来,而是只弹到 “(” ,因此,现在栈里面从栈顶一直往下弹,弹到 “(” 为止。目前的状况看下图。
在这里插入图片描述

下一个, “÷” ,跟栈顶符号 “×” 比优先级为同级,则将栈中元素都弹出来,即 “×” 弹出,将 “÷” 压入栈中。因为转换规则是,当前符号与栈顶符号比较,优先级大于栈顶符号,才不弹出直接压入;否则就要先弹出,即清空栈再压入。

简单说就是,当前符号优先级大于栈顶符号优先级时,不弹出直接压入;小于等于时,弹出再压入。目前的状况看下图。

在这里插入图片描述

下一个, “3” ,直接输出,此时输出为:563+×3。下一个, “-” ,这个符号跟栈顶符号比较,优先级低于栈顶符号,so,弹出栈中元素,把 “-” 压入栈中。目前的状况看下图。

在这里插入图片描述

下一个, “1” ,直接输出,此时输出为:563+×3÷1。原中值表达式没有元素了,最后一步操作将栈内还没弹出的符号都弹出。【在计算机中,其实是自动向中缀表达式末尾填充一个 “#” ,由于 “#” 优先级最低,这样在搜索到 “#” 时,就会清空栈。但 “#” 不参与表达式的计算,就是输出时,没有 “#” 。这和数组最后一位是结束符是同样的道理。】弹出时符号写在输出中的顺序是,按从栈底到栈顶这个顺序在输出表达式中从左到右列出。最后的输出就是:563+×3÷1-

解题思路:

1 用集合依次存下数字
2 如果是计算符号,将集合中的后2位数字进行计算
3 将在计算过程中使用过的元素remove,并新增计算的结果元素到集合中
4 最终集合只留下一个元素,即最终结果

import java.util.*;


public class Solution {
    /**
     * 
     * @param tokens string字符串一维数组 
     * @return int整型
     */
    public int evalRPN (String[] tokens) {
        List<Integer> numList = new ArrayList<>();
        for (String token : tokens) {
            boolean isTrue = false;
            for (int i = 0; i < token.length(); i++) {
                isTrue =token.charAt(i)>=48 && token.charAt(i)<=57;
            }
            if (isTrue) {
                numList.add(Integer.valueOf(token));
            } else {
                int size = numList.size();
                switch (token) {
                    case "+":
                        int num = numList.get(size - 2) + numList.get(size - 1);
                        numList.remove(size - 1);
                        numList.remove(size - 2);
                        numList.add(num);
                        break;
                    case "-":
                        num = numList.get(size - 2) - numList.get(size - 1);
                        numList.remove(size - 1);
                        numList.remove(size - 2);
                        numList.add(num);
                        break;
                    case "*":
                        num = numList.get(size - 2) * numList.get(size - 1);
                        numList.remove(size - 1);
                        numList.remove(size - 2);
                        numList.add(num);
                        break;
                    case "/":
                        num = numList.get(size - 2) / numList.get(size - 1);
                        numList.remove(size - 1);
                        numList.remove(size - 2);
                        numList.add(num);
                        break;
                }

            }
        }
        return numList.get(0);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值