逆波兰计算器(后缀计算器)

后缀表达式计算器思路:

 

中缀转后缀思路:

  1. 设置两个栈,运算符栈s1,辅助栈s2
  2. 从左到右遍历中缀表达式
  3. 遇到操作数,压入s2
  4. 遇到括号
    1. 如果是左括号,直接压入s1
    2. 如果是右括号,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为主,并丢弃这一对括号
  5. 遇到操作符
    1. 如果s1为空,直接压入s1
    2. 否则,若低于s1栈顶操作符的优先级,则弹出s1栈顶的运算符,并压入s2,然后再次将扫描处的操作符与s1栈顶元素的优先级比较,直到高于它(或者s1没有元素了),便停止。再将其压入s1栈
  6. 将s1中剩余的运算符依次弹出并压入s2
  7. 依次弹出s2的元素,再逆序,即是对应的后缀表达式
package 数据结构;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class NiBoLanCalculator {
    
    //将字符串表达式放入ArrayList,方便遍历
    //注意表达式中操作数与操作符之间必须有空格(包括“()”)
    public static List<String> toArrayList(String expression){
        String[] split = expression.split(" ");
        List<String> list = new ArrayList<>();
        for (String ele : split) {
            list.add(ele);
        }
        return list;
    }

    //将中缀转为后缀
    public static List<String> midToEnd(List<String> list) {
        Stack<String> s1 = new Stack<>();
        //由于s2实际上并没有pop操作,且还需将其逆序才是结果,因此可以直接用ArrayList替代。
        ArrayList<String> s2 = new ArrayList<>() ;
        int sign = 0;
        for (String ele : list) {
            if (ele.matches("\\d+")) {
                s2.add(ele);
            } else if (ele.equals("(") || ele.equals(")")) {
                if (ele.equals("(")) {
                    s1.push(ele);
                } else {
                    while (!s1.peek().equals("(")) {
                        s2.add(s1.pop());
                    }
                    s1.pop();//!!!
                }
            } else if (ele.equals("+") || ele.equals("-") || ele.equals("*") || ele.equals("/")) {
                while (!s1.isEmpty() && priority(ele) <= priority(s1.peek())){
                    s2.add(s1.pop());
                }
                s1.push(ele);
            }
        }
        while (!s1.isEmpty()){
            s2.add(s1.pop());
        }
        return s2;
    }
    
    //进行计算
    public static int calculate(List<String> list){
        Stack<String> stack = new Stack<>();
        //从左往右扫描表达式,若是操作数直接入栈,遇到操作符则取出栈顶前两个元素进行运算,计算结果重新压入栈顶
        for(String ele: list){
            if (ele.matches("\\d+")){   //匹配一个不限于一位的数
                stack.push(ele);
            }else{
                int num2 = Integer.parseInt(stack.pop());
                int num1 = Integer.parseInt(stack.pop());
                int res = 0;

                if (ele.equals("+")){
                    res = num1 + num2;
                }else if (ele.equals("-")){
                    res = num1 - num2;
                }else if (ele.equals("*")){
                    res =  num1 * num2;
                }else if (ele.equals("/")){
                    res = num1 / num2;
                }else throw new RuntimeException("运算符有误");
                stack.push(res + "");
            }
        }
        return Integer.parseInt(stack.pop());
    }

    //判断优先级
    public static int priority(String c){
        return switch (c) {
            case "+", "-" -> 1;
            case "*", "/" -> 2;
            default -> -1;
        };
    }
}

 

posted @ 2022-03-26 10:22  Amazzzzing  阅读(379)  评论(0)    收藏  举报