学习笔记-中缀表达式转逆波兰表达式(后缀表达式)

中缀表达式转后缀表达式实现计算器(支持括号以及小数点不支持空白符)

思路图:
在这里插入图片描述
这里的s2栈我直接改为ArrayList因为最后是栈的结果的逆序,用ArrayList即可。ok上代码:

public class PolandNotation {
    public static void main(String[] args) {
        //定义中缀表达式
        String expression = "1+((2.2+3.3)*4)-5";
        List<String> expressionArrayList = toInFixExpression(expression);
        List<String> suffixList = polandNotationArrayList(expressionArrayList);
        //先定义一个逆波兰表达式
        //String suffixExpression = "3 4 + 5 * 6 -";
        //List<String> suffixList = getListString(suffixExpression);
        Double res = calLater(suffixList);
        System.out.println("最终的结果是:"+res);
    }

    /**
     * 中缀表达式转为ArrayList
     * @param toExpression 中缀表达式字符串
     * @return 中缀表达式的ArrayList
     */
    public static List<String> toInFixExpression(String toExpression){
        List<String> ls = new ArrayList<String>();
        int i =0;
        String str;
        char c;
        do {
            //如果c是一个非数字
            if ((c = toExpression.charAt(i)) < 48 || (c = toExpression.charAt(i)) > 57 && (c = toExpression.charAt(i)) != 46) {
                ls.add(String.valueOf(c));
                i++;
            }else {
                //是一个数字,就要考虑多位数的问题
                str = "";
                while (i < toExpression.length() && (c = toExpression.charAt(i)) >= 48 && (c = toExpression.charAt(i)) <= 57 || i < toExpression.length() && (c = toExpression.charAt(i)) == 46) {
                    //拼接
                    str += c;
                    i++;
                }
                ls.add(str);
            }
        }while (i < toExpression.length());
        return ls;
    }
    /**
     * 逆波兰表达式转为数组
     * @param suffixExpression 逆波兰表达式字符串
     * @return 数组
     */
    public static List<String> getListString(String suffixExpression){
        String[] split = suffixExpression.split(" ");
        List<String> lis = new ArrayList<String>();
        for (String ele: split){
            lis.add(ele);
        }
        return lis;
    }

    /**
     * 将中缀表达式转为逆波兰表达式
     * @param ls 中缀表达式ArrayList
     * @return 逆波兰表达式ArrayList
     */
    public static List<String> polandNotationArrayList(List<String> ls){
        //定义一个栈
        Stack<String> s1 = new Stack<String>();
        //可以用ArrayList即可
        List<String> s2 = new ArrayList<String>();
        for (String item: ls){
            //如果是一个数就加入到s2
            if (item.matches("\\d+") || item.matches("\\d+[.]{1}\\d+")){
                s2.add(item);
            }else if (item.equals("(")) {
                s1.push(item);
            }else if (item.equals(")")){
                //如果是右括号,则依次弹出栈顶符号,并加入s2,直到遇到(为止
                while (!s1.peek().equals("(")) {
                    s2.add(s1.pop());
                }
                //将(消除
                s1.pop();
            }else {
                //当item的优先级小于或者等于s1的栈顶运算符时
                while (s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item)) {
                    s2.add(s1.pop());
                }
                //还需要将item压到s1中
                s1.push(item);
            }
        }
        while (s1.size() != 0){
            s2.add(s1.pop());
        }
        return s2;
    }
    /**
     * 计算逆波兰表达式
     * @param list 需要计算的后缀表达式(逆波兰表达式)
     * @return 结果
     */
    public static Double calLater(List<String> list){
        //先创建一个数栈
        Stack<String> stack = new Stack();
        for (String ch: list){
            if (ch.matches("\\d+") || ch.matches("\\d+[.]{1}\\d+")){
                stack.push(ch);
            }else {
                Double num1 = Double.parseDouble(stack.pop());
                Double num2 = Double.parseDouble(stack.pop());
                double res = 0;
                if (ch.equals("+")){
                    res = num1 + num2;
                }else if (ch.equals("*")){
                    res = num1 * num2;
                }else if (ch.equals("-")){
                    res = num2 - num1;
                }else if (ch.equals("/")){
                    res = num2 / num1;
                }else {
                    throw new RuntimeException("运算符错误");
                }
                stack.push("" + res);
            }
        }
        return Double.parseDouble(stack.pop());
    }
}
//判断符号优先级的类
class Operation{
    private static int ADD = 1;
    private static int SUB = 1;
    private static int MUL = 2;
    private static int DIV = 2;

    /**
     * 判断符号优先级
     * @param oper 符号
     * @return 优先级数字
     */
    public static int getValue(String oper){
        int result = 0;
        switch (oper){
            case "+":
                result = ADD;
                break;
            case "-":
                result = SUB;
                break;
            case "*":
                result = MUL;
                break;
            case "/":
                result = DIV;
                break;
            default:
                break;
        }
        return result;
    }
}
原创文章 23 获赞 23 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Shine_QianMo/article/details/105161702