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

Posted f-society

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了中缀表达式转后缀表达式(逆波兰表达式)相关的知识,希望对你有一定的参考价值。

package com.example.test.util;

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

public class FormulaUtils {
    /**
     * 转逆波兰表达式  "a+ b *c+(d*e+f)*g" => ["a","b","c","*","+","d","e","*","f","+","g","*","+"]
     * @param exp "a+ b *c+(d*e+f)*g"
     * @author wangxiaolei
     * @date 2020/4/17 21:22
     * @return java.util.List<java.lang.String>
     */
    public static List<String> toReversePolishNotaion(String exp){
        if(!StringUtils.isEmpty(exp)){
            try{
                List<String> reversePolishNotation = new ArrayList<>();
                List<String> expUnit = splitExp(exp);
                Stack<String> stack = new Stack<>();  //操作符辅助栈
                for (String op : expUnit) {
                    switch (op){
                        case "(":   //遇到 "(" 直接入栈
                        case "(":
                            stack.push(op);
                            break;
                        case ")":  // 遇到")"则把栈内元素全部出栈直至遇到"("。注意:"("不输出
                        case ")":
                            while(!stack.isEmpty()){
                                String pop = stack.pop();
                                if("(".equals(pop) || "(".equals(pop)){
                                    break;
                                }
                                reversePolishNotation.add(pop);
                            }
                            break;
                        case "+":  //遇到四则运算则 将栈内元素 >= 自己优先级的全部出栈并输出,再将自己入栈
                        case "-":
                        case "*":
                        case "/":
                            while(!stack.isEmpty() && getPriority(stack.peek()) >= getPriority(op)) {  //当栈顶元素优先级>=当前操作符优先级
                                reversePolishNotation.add(stack.pop());
                            }
                            stack.push(op);
                            break;
                        default:  //操作数 直接入栈
                            reversePolishNotation.add(op);
                            break;
                    }
                }
                while(!stack.isEmpty()){ //剩余操作符出栈
                    reversePolishNotation.add(stack.pop());
                }
                return reversePolishNotation;
            }catch (Exception e){
                e.printStackTrace();
                throw new RuntimeException("解析表达式错误,exp:"+exp, e);
            }
        }
        return new ArrayList<>();
    }

    /**
     * 操作符优先级
     * @param op
     * @author wangxiaolei
     * @date 2020/4/17 21:23
     * @return int
     */
    public static int getPriority(String op){
        switch (op){
            case "(":
            case "(":
                return 0;
            case "+":
            case "-":
                return 1;
            case "*":
            case "/":
                return 2;

        }
        return -1;
    }
    /**
     * 根据操作符拆分公式
     * @param exp a+ b /3 +(2 + cccc)+(123) => ["a","+","b","/","3","+","(","2","+","cccc",")","+","(","123",")"]
     * @author wangxiaolei
     * @date 2020/4/17 18:40
     * @return java.util.List<java.lang.String>
     */
    public static List<String> splitExp(String exp){
        //拆分公式
        List<String> expUnit = new ArrayList<>();
        String tmp = "";
        for(int i=0; i<exp.length();i++){
            char ch = exp.charAt(i);
            switch (ch){
                case ‘ ‘:
                    continue;
                case ‘(‘:
                case ‘(‘:
                case ‘)‘:
                case ‘)‘:
                case ‘+‘:
                case ‘-‘:
                case ‘*‘:
                case ‘/‘:
                    if(!StringUtils.isEmpty(tmp)){
                        expUnit.add(tmp);
                    }
                    expUnit.add(String.valueOf(ch));
                    tmp = "";
                    break;
                default:
                    tmp += ch;
                    break;
            }
        }
        if(!StringUtils.isEmpty(tmp)){
            expUnit.add(tmp);
        }
        return expUnit;
    }



    /**
     * 计算逆波兰表达式
     * @param reversePolishNotation 逆波兰表达式 ["a","+","b","/","3","+","(","2","+","cccc",")","+","(","123",")"]
     * @author wangxiaolei
     * @date 2020/4/17 21:31
     * @return java.lang.String
     */
    public static String calculateReversePolishNotation(List<String> reversePolishNotation){
        Stack<String> stack = new Stack<>();
        for (String s : reversePolishNotation) {
            if(isOperator(s)){
                String b = stack.pop();
                String a = stack.pop();
                stack.push("("+a+s+b+")");
            }else{
                stack.push(s);
            }
        }
        if(!stack.isEmpty()){
            return stack.pop();
        }
        return "";
    }
    public static boolean isOperator(String str){
        return str.matches("[\+\-\*\/]");
    }

    public static void main(String[] args) throws Exception {
//        String a = "A+B*(C-D)-E*F";
//        String a = "a+ b /3 +(2 + cccc)+(123)";
        String a = "a+ b *c+(d*e+f)*g";
        List<String> strings = toReversePolishNotaion(a);
        System.out.println(JacksonUtils.obj2json(strings));
        System.out.println(calculateReversePolishNotation(strings));
    }


}

 

以上是关于中缀表达式转后缀表达式(逆波兰表达式)的主要内容,如果未能解决你的问题,请参考以下文章

算法逆波兰式(后缀表达式)的计算 & 中缀表达式转后缀表达式(逆波兰式)

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

算法中缀表达式转成后缀表达式(逆波兰表达式)再计算得出结果

算法中缀表达式转成后缀表达式(逆波兰表达式)再计算得出结果

shunting-yard 调度场算法中缀表达式转逆波兰表达式

逆波兰表达式