栈(前缀、中缀、后缀表达式及逆波兰计算器的实现)

前缀表达式(波兰表达式)

1.前缀表达式的运算符位于操作数之前

2.例如(3+4)x5-6的前缀表达式就是:-x+ 3 4 5 6;

计算机求值过程

从右至左扫描前缀表达式,遇到数字的时候将数字压入堆栈,遇到运算符的时候弹出栈顶的两个元素,用扫描到的这个运算符对它们做相应的运算,并将结果再次入栈;

重复上述过程,直到扫描到表达式的最左端,最后运算得出的值即是表达式的结果;

例如上面的: - x + 3 4 5 6前缀表达式

1.从右至左扫描,将6 5 4 3 依次压入栈中;

2.扫描到+号,则取出栈顶两个元素即3和4,进行运算得到7再加入栈中;

3.扫描到x号,则取出栈顶两个元素即7和5,得到结果35,加入到栈中;

4.扫描到-号,则取出35和6两个元素进行最后的运算,最终得到结果29=》运算完毕;

中缀表达式

就是我们常见的运算表达式,例如(3+4)x5-6;

中缀表达式的求值是我们人最熟悉的,但是对计算机来说却不好操作,就跟我们上面实现综合计算器一样, 它不仅需要两个栈来存储,并且在进行运算的时候还需要去判断运算符的优先级,因此肯定是不方便的;

而通过我们刚刚介绍的前缀表达式的计算机实现来讲,只要前缀表达式是正确的,我们不需要去判断运算符的优先级,并且在一个栈中就可以完成整个表达式的运算;

后缀表达式(逆波兰表达式)

与前缀表达式相似,只是运算符位于操作数之后

例如(3+4)x5-6对应的后缀表达式就是:3 4 + 5 x 6 -;

计算机求值过程

左至右扫描表达式,遇到数字时将数字压入堆栈,遇到运算符时弹出栈顶的两个数,用运算符对它们做相应的运算,并将结果再次入栈,重复上述过程直到表达式的最右端,最后运算得出的值即为表达式的结果(也就是跟前缀表达式求值是相反的);

例如上面的:3 4 + 5 x 6 -,的求值步骤如下:

1.从左至右扫描,将3,4压入堆栈;

2.扫描到+号,取出栈顶两个元素即3 4,进行运算得到7压入堆栈;

3.扫描到5,将其压入堆栈;

4.扫描到x号,取出栈顶两个元素即5,7进行运算 得到35,压入堆栈;

5.扫描到6,压入堆栈;

6.扫描到-号,取出35 6,进行运算,得到29,即最终结果,运算完毕(需要次顶元素在前,栈顶元素在后进行运算);

基于栈实现逆波兰计算器

要求

1输入一个逆波兰表达式(后缀表达式),我们使用系统提供的栈(Stack)计算其结果;

2.支持小括号和多位数整数,我们这里主要讲的是数据结构,因此计算器进行了简化,只支持整数运算;

思路分析

1.我们将逆波兰表达式以字符串的形式呈现,并且每个字符之间用空格或者其他符号隔开;

2.因为逆波兰表达式的计算是从左往右,因此我们将该字符串基于分隔符分割,得到所有的字符,并且存到List集合中;

3.创建一个Stack对象(Java.Util包下面的),遍历List集合,如果遍历到的元素是数字,则直接push进栈中;如果遍历得到的是符号,则取出栈中两个元素,与该符号进行运算

4.再将运算的结果push进栈中;

5.扫描完成之后再取出栈中的元素(这个时候栈中只有一个元素,即最终的结果);

代码实现

   /**
     *
     * @Author:Strine
     * 逆波兰计算器的实现
     * */
    public static String getReverse(List<String> str){
        Stack<String> stack = new Stack<>();
        for (int i = 0; i < str.size(); i++) {
            if (!isOper(str.get(i))){
                stack.push(str.get(i));
            }else {
                String num1 = stack.pop();  //栈顶元素
                String num2 = stack.pop();  //次顶元素
                String ret = getRet(Integer.parseInt(num1), Integer.parseInt(num2), str.get(i));
                stack.push(ret);
            }
        }
        String ret= stack.pop();
        return ret;
    }
    /**
     *
     * 判断是不是一个运算符
     * */
    public static boolean isOper(String oper){
        return "+".equals(oper) || "-".equals(oper) || "*".equals(oper) || "/".equals(oper);
    }
    public static String getRet(int num1,int num2,String oper){
        //用于存放计算的结果
        int ret = 0;
        switch (oper){
            case "+":
                ret=num1+num2;
                break;
            case "-":
                ret=num2-num1;
                break;
            case "*":
                ret=num1*num2;
                break;
            case "/":
                ret=num2/num1;
                break;
        }
        return String.valueOf(ret);
    }

效果展示

计算:4*5-8+60+8÷2转成逆波兰表达式后的结果如下:

 public static void main(String[] args) {
        String str = "4 5 * 8 - 60 + 8 2 / +";
        List<String> list = getList(str);
        String ret = ReversePolish.getReverse(list);
        System.out.println(str+"逆波兰表达式的结果是:"+ret);
    }
    public static List<String> getList(String str){
        String[] tar = str.split(" ");
        List<String> list = new ArrayList<>();
        for (int i = 0; i < tar.length; i++) {
            list.add(tar[i]);
        }
        return list;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Strine

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值