前序表達式&中序表達式&后序表達式


前序表達式 , 中序表達式 , 后序表達式

  • 中序表達式

    中序表達式即我們日常使用的表達式,從左往右閱讀,結構清晰,但是需要括號改變優先級,對計算機不友好

    eg:(1+4)*3+10/5,2*3/(2-1)+3*(4-1)

  • 前序表達式(波蘭表示法Polish notation,或波蘭記法)

    前序表達式的特點是操作符置於操作數前面,如果操作符的元數(+是二元操作符,故元數是2),則語法上不需要括號仍然能被無歧義的解釋,不需要口號改變優先級。

    eg:

    中序表達式: (1+4)*3+10/5
    前序表達式: + * + 1 4 3 / 10 5
    
    前序表達式的計算:
    eg:
    	+ * + 1 4 3 / 10 5
    step1:	10 / 5 => 2 
    new expression: + * + 1 4 3 2
    step2:	1 + 4 => 5 
    new expression: + * 5 3 2
    step3:	5 * 3 => 15
    new expression: + 15 2
    step4:	15 + 2 => 17
    
    前序表達式的求值:
    首先要從右至左掃描表達式,從右邊第一個字符開始判斷,如果當前字符是數字則繼續掃描,如果當前字符是運算符,將運算符右邊最近的兩個數字做運算,結果作為新的字符記錄下來。
    一直掃描到表達式的最左端時,最后運算的值也就是表達式的值。
    
  • 后序表達式(逆波蘭表示法(Reverse Polish notation,RPN,或逆波蘭記法)

    后序表達式所有的操作符置於操作數后面,因此也被稱為后綴表示法。逆波蘭表示法不需要括號標識操作符的優先級。

    eg:

    中序表達式: (1+4)*3+10/5
    后序表達式: 1 4 + 3 * 10 5 / +
    
    后序表達式的計算:
    eg:
    	1 4 + 3 * 10 5 / +
    step1:	1 + 4 => 5 
    new expression: 5 3 * 10 5 / +
    step2:	5 * 3 => 15
    new expression: 15 10 5 / +
    step3:	10 / 5 => 2
    new expression: 15 2 +
    step4:	15 + 2 => 17
    
    后序表達式的求值:
    后序表達式的求值和前序表達式十分相似,后序表達式是從左至右掃描表達式,從左邊第一個字符開始判斷,如果的那個字符是數字繼續掃描,
    如果是運算符,將運算符左邊最近的兩個數字做運算,結果作為新的字符記錄下來。一直掃描到表達式的最右端時,最后運算的值也就是表達式的值。
    

中序表達式轉后序表達式(暫時只實現四則運算級別的轉化)

  • 創建一個隊列和一個操作符棧
  • 遇到操作數則送入隊列
  • 遇到操作符則送入棧
    • 遇到加減乘除運算符:彈出所有優先級大於或等於該運算符的棧頂元素,然后該運算符入棧
    • 遇到”(“括號直接入棧
    • 遇到”)"括號則將棧內直到“(”括號的所有操作符送入隊列
  • 執行完成后,先輸出隊列內容,在輸出棧內容,最終結果即是后序表達式
/**
 * 先序表達式 -> 后序表達式
 */
public String infixToPostfix(String[] elements) {
    String res = "";

    Stack<String> stack = new Stack<>();
    Queue<String> queue = new Queue<>();
    for (int i = 0; i < elements.length; i++) {
        String s = elements[i];

        if (s.equals("(")) {
            stack.push(s);
            continue;
        }
        if (s.equals(")")) {
            String pop = stack.pop();
            while (!pop.equals("(")) {
                queue.enqueue(pop);
                pop = stack.pop();
            }
            continue;
        }

        //碰到"+"或 "-"運算符
        if (s.equals("+") || s.equals("-")){
            if (stack.isEmpty()){
                stack.push(s);
                continue;
            }
            while (!stack.isEmpty() && !stack.peek().equals("(")){
                queue.enqueue(stack.pop());
            }
            stack.push(s);
            continue;
        }

        //碰到"*"或 "/"運算符
        if (s.equals("*") || s.equals("/")){
            if (stack.isEmpty()){
                stack.push(s);
                continue;
            }
            boolean peek = stack.peek().equals("*") || stack.peek().equals("/");
            while (!stack.isEmpty() && peek) {
                queue.enqueue(stack.pop());
            }
            stack.push(s);
            continue;
        }
        queue.enqueue(s);
    }

    //拼接后序表達式
    do{
        res += queue.dequeue() + " ";
    } while (!queue.isEmpty());
    do {
        res += stack.pop() + " ";
    } while (!stack.isEmpty());
    return res;
}

后序表達式的計算(暫時只實現了四則運算)

  • 從左至右掃描表達式
  • 如果字符是數字繼續掃描,如果是操作符,取左邊最近的兩個操作數,運算后將結果壓入棧中
  • 掃描到表達式的最右端時,最后運算的值也就是表達式的值
/**
 * 1.3.11  計算后序表達式的值
 */
public class EvaluatePostfix {

    public int evaluate(String[] postfix){
        Stack<String> stack = new Stack<>();
        for (int i = postfix.length - 1; i >= 0; i--) {
            stack.push(postfix[i]);
        }

        Stack<String> tmp = new Stack<>();
        String res = "";
        while (!stack.isEmpty()) {
            String pop = stack.pop();
            if (pop.equals("*") || pop.equals("/") || pop.equals("+") || pop.equals("-")){
                int rightValue = Integer.valueOf(tmp.pop());
                int leftValue = Integer.valueOf(tmp.pop());
                int sum = evaluate(leftValue, rightValue, pop);
                stack.push(sum + "");
                while (!tmp.isEmpty()){
                    stack.push(tmp.pop());
                }
                continue;
            }
            tmp.push(pop);
            res = pop;
        }
        return Integer.parseInt(res);
    }

    public int evaluate(int a, int b, String operator){
        switch (operator){
            case "*" : return a * b;
            case "/" : return a / b;
            case "+" : return a + b;
            case "-" : return a - b;
            default: throw new IllegalArgumentException("operator must be \"* / + -\"");
        }
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM