中缀转后缀字符串表达式求值

概念

  1. 前缀表达式(波兰表达式)
    运算符位于操作数前,右到左依次入栈
  2. 中缀表达式
    从左到右依次入栈,一般转为后缀表达式
  3. 后缀表达式(逆波兰表达式)
    运算符位于操作数后

中缀转后缀(思路)

  1. 初始化俩个栈,运算符s1与存储中间结果栈S2
  2. 左到右扫描中缀表达式
  3. 遇到操作数,直接入S2
  4. 遇到运算符,比较与S1栈顶运算符优先级比较
    • 如果运算符栈为空,直接入栈
    • 如果优先级比S1栈顶优先级高,直接入栈
    • 否则将S1出栈到S2,再次跳转到第四步,进行比较
  5. 遇到括号
    • 左括号,直接入栈
    • 有括号,依次弹出,并入S2,直到遇到左括号
  6. 重复Step 2~5 直到到达表达式最右端
  7. 将S1有依次弹出,并压入S2
    8.S2中的元素依次弹出,逆序就是后缀表达式

代码实现

public class PolandExpression {

    public static void main(String[] args) {
        PolandExpression pe = new PolandExpression();
//        List mList = pe.middlePolandToList("(3+4)*5-6");
        List mList = pe.middlePolandToList("4*5-8+60+8/2");
        System.out.println("中缀表达式 : " + mList);
        List aList = pe.middleToAffter(mList);
        System.out.println("后缀表达式 : " + aList);
        pe.calculation(aList);
    }
    
    public List middleToAffter(List mStr) {
        List aList = new ArrayList<>();
        Stack operStack = new Stack<>();
        Stack numStack = new Stack<>();
        int currIndex = 0;
        while (true) {
            if (currIndex > mStr.size() - 1) {
                break;
            }
            String curStr = mStr.get(currIndex);
            if (strIsNum(curStr)) {
                //数字直接入栈
                numStack.push(curStr);
            } else {
                if ("(".equals(curStr)) {
                    operStack.push(curStr);
                } else if (")".equals(curStr)) {

                    while (true) {
                        String top = operStack.pop();
                        if ("(".equals(top)) {
                            break;
                        } else {
                            numStack.push(top);
                        }
                    }
                } else {
                    if (operStack.isEmpty()) {
                        //字符栈为空,直接入栈
                        operStack.push(curStr);
                    } else if (compareChar(curStr.charAt(0), operStack.peek().charAt(0))) {
                        //字符优先级高于栈顶
                        operStack.push(curStr);
                    } else {
                        numStack.push(operStack.pop());
                        continue;
                    }
                }
            }
            currIndex++;
        }

        while (true) {
            if (operStack.isEmpty()) {
                break;
            } else {
                numStack.push(operStack.pop());
            }
        }

        while (true) {
            if (numStack.isEmpty()) {
                break;
            } else {
                aList.add(numStack.pop());
            }
        }

        numStack.stream().forEach(str -> {
            aList.add(str);
        });
        for (int i = 0; i < aList.size() / 2; i++) {
            int size = aList.size();
            String m = aList.get(i);
            aList.set(i, aList.get(size - 1 - i));
            aList.set(size - 1 - i, m);
        }
        return aList;

    }

    public boolean strIsNum(String str) {
        return str.matches("\\d+");
    }


    /**
     * 中缀表达式转List
     */
    public List middlePolandToList(String str) {
        List list = new ArrayList<>();
        String num = "";
        for (int i = 0; i < str.length(); i++) {
            char curChar = str.charAt(i);
            if (!Character.isDigit(curChar)) {
                list.add(Character.toString(curChar));
            } else {
                if (i == str.length() - 1) {
                    list.add(Character.toString(curChar));
                } else if (Character.isDigit(str.charAt(i + 1))) {
                    num += curChar;
                    continue;
                } else {
                    num += curChar;
                    list.add(num);
                }
                num = "";
            }
        }
        return list;
    }


    public int cal(int num1, int num2, char oper) {
        int resul = 0;
        switch (oper) {
            case '*':
                resul = num1 * num2;
                break;
            case '-':
                resul = num2 - num1;
                break;
            case '+':
                resul = num1 + num2;
                break;
            case '/':
                resul = num2 / num1;
                break;
            default:
                break;
        }
        return resul;
    }

    /**
     * 比较字符优先级
     */
    public boolean compareChar(char char1, char char2) {

        if (char2 == '(' || char2 == ')') {
            return true;
        }

        if (char1 == '*' || char1 == '/') {
            if (char2 == '+' || char2 == '-') {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
    
    public void calculation(List aList) {
        int curIndex = 0;
        Stack stack = new Stack<>();
        while (true) {
            if (curIndex >= aList.size()) {
                break;
            }
            String curStr = aList.get(curIndex);
            if (strIsNum(curStr)) {
                stack.push(curStr);
            } else {
                int num1 = Integer.parseInt(stack.pop());
                int num2 = Integer.parseInt(stack.pop());
                int cal = cal(num1, num2, curStr.charAt(0));
                stack.push(cal + "");
            }
            curIndex++;
        }
        System.out.println(stack.pop());
    }
}

你可能感兴趣的:(中缀转后缀字符串表达式求值)