数据结构之后缀表达式求值(java实现)

数据结构之后缀表达式求值(java实现)

前记

​ 今天在刷leet code的时候刷到了一道题,后缀表达式(逆波兰表达式)求值,我花了一会儿写了一下它的解法。但是今天我不谈什么是后缀表达式,有兴趣的同学可以去论坛上看看其他人聊后缀表达式的问题,单就解题来说,我用了最为常规的办法,应该也是初学者最容易理解的方法写的,故代码数量较多,一定要读下去哦!

图解分析

首先我们拿出一个后缀表达式的例子,这里我直接用力扣上的测试用例。

String[] expression = {"2", "1", "+", "3", "*"}; 
//其转化为中缀表达式就是 ((2 + 1) * 3) = 9

对于后缀表达式求值,我们有这样一个规则:

1. ==遇到数字则入栈。==
2. ==遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。==

我相信有很多同学会有疑惑为什么直接接给出了这个规则,怎么来的这个规则,其实我也会有这样的疑惑,但是我觉得有可能是因为计算机的工作原理,栈的工作原理所知,以前的程序员可能就总结出了很多规律供我们使用。实际上我们不用事事都去追根溯源,要学会使用工具和思考,该深思的地方才去深思,避免重复造轮子。

通过理解规则我们首先能想到的是,这个题我们应该要用到栈(Stack),所以我尝试用图的方式来演示该工作过程。

第一步:

{“2”, “1”, “+”, “3”, “*”}

首先遍历的是第一个元素 “2”,此时是数字,直接入栈。

数据结构之后缀表达式求值(java实现)_第1张图片

第二步:

{“2”, “1”, “+”, “3”, “*”}

遍历下一个元素 “1” 依旧是数字,也是直接入栈。
数据结构之后缀表达式求值(java实现)_第2张图片

第三步:

{“2”, “1”, “+”, “3”, “*”}

继续遍历下一个元素 “+”,此时我们遇到了规则里面的第二个条件,不是数字了,我们将从栈中弹出两个数字,进行运算,也就是==1 和 2==进行1+2=3,并将3入栈。

数据结构之后缀表达式求值(java实现)_第3张图片

第四步:

{“2”, “1”, “+”, “3”, “*”}

遍历到第四个元素 “3”,直接入栈。

数据结构之后缀表达式求值(java实现)_第4张图片

第五步:

{“2”, “1”, “+”, “3”, “*”}

遍历最后一个元素 “*”,此时又要从栈里面弹出两个数字,进行运算,也就是3*3=9,再将9入栈。

数据结构之后缀表达式求值(java实现)_第5张图片

当遍历完链表中所有元素时,栈中的唯一的一个数字即为最终的运算结果。

接下来,我们准备进行代码实现。

代码实现

我们首先定义一个方法对弹出来的数字进行运算。

值得注意的是,在后缀表达式求值时,从栈中弹出来的数,越靠近栈底的数,就要作为被减数,被除数

代码如下:

 /**
     * 该方法用于计算
     */
    public static int cal(int num1,int num2,String oper){
        int result = 0;
        switch (oper){
            case "+":
                result = num1 + num2;
                break;
            case "-":
                result = num2 - num1;  //靠近栈底的做被减数
                break;
            case "*":
                result = num1 * num2;
                break;
            case "/":
                result = num2 / num1; //靠近栈底的做被除数
                break;
            default:
                break;
        }
        return result;
    }

然后还需要定义一个用于遍历字符数组,完成入栈弹栈操作的方法

代码如下:

public static int calculate(List<String> ls){
        Stack<String> stack = new Stack<>();
        for (String l : ls) {
            if (l.matches("-?\\d+")){//正则表达式匹配数字
                stack.push(l);
            }else{
                String num1 = stack.pop();
                String num2 = stack.pop();
                int calculate = cal(Integer.parseInt(num1), Integer.parseInt(num2), l);
                stack.push(String.valueOf(calculate));
            }
        }
        return Integer.parseInt(stack.pop());
    }

在对数字进行判别的时候我采用了正则表达式,并考虑到可能为多位数,负数的情况,不理解的同学可以去了解一下正则表达式。

最后就是测试了:

 @Test
    public void test() {
        //定义一个逆波兰表达式
        String[] surffixExpression = {"2", "1", "+", "3", "*"};
        int result = calculate(surffixExpression);
        System.out.println(result);

    }
后记

至此,后缀表达式的求值就完成了,此方法我认为是初学者最容易理解的方法,不懂的同学可以多画图去理解,一边画图一边思考,算法题画图还是很重要的,动起来,一起学习。

你可能感兴趣的:(数据结构自学路,数据结构,java,leetcode,算法)