中綴表達式轉后綴表達式


  先看幾個中綴表達式和它們對應的后綴表達式的例子

  可以看到操作數a, b, c 在中綴表達式中的順序和在后綴表達式中的順序是一致的,但操作符的順序可能不一致,因為在中綴表達式中操作符有優先級,括號也能改變運算的優先級,這些都要在后綴表達式中體現出來,后綴表達式中沒有括號。那怎么轉化呢?

  1,創建一個變量,初始化為空的字符串,來表示要完成的后綴表達式,創建一個字符棧,用來存儲操作符

  2,從左向右依次掃描中綴表達式,

    遇到操作數,直接加到后綴表達式的后面 ,因為,在中綴表達式和后綴表達式中,操作數的順序是一樣的,

    遇到操作符,要先存起來,存到棧中,因為操作符有優先級,它要和后面的操作符比較優先級,然后才能決定把它放到什么哪個位置。

      如果棧為空,直接把操作符放入棧中

      如果棧不為空,比較優先級。

        如果遇到的操作符比棧頂中的操作符優先級高,把遇到的操作符放入棧中。

        如果遇到的操作符和棧頂操作符的優先級相等,這要考慮操作符的結合性,它是從左到右結合,還是從右到左結合。

          從左到右接合,就是操作數屬於它前面的操作符而不是它后面操作符。+, - , * , / 就是從左向右結合,比如a-b+c中的b是-的操作數,而不是+的操作數,整個表達式,也是從左向右計算的。

          從右向左結合,操作數屬於它前面的操作符而不是它后面操作符,比如階乘。a ^ b ^ c, b是第二個^的操作數,而不是第一個^的操作數,整個表達式也是從右向左計算,a ^ (b ^ c)。

          如果從左向右接合,那就彈棧,把操作符放到后綴表達式中,如果從右向左結合,則把遇到的操作符放入棧中(和優先級高的情況一致)

        如果遇到的操作符比棧頂中的操作符優先級低,那就彈棧,把操作符放到后綴表達式中

    遇到(,放到字符棧,因為要等到)才能知道怎么操作。

    遇到),依次從字棧中彈棧,放到后綴表達式中,直到遇到(,  遇到(, 要把它彈棧,然后舍棄掉。

  3,循環完畢,如果字符棧中還有操作符,依次彈棧放到后綴表達式中,最終棧為空,得到完整的后綴表達式。

  舉幾個例子,來理解一下轉化過程,如果遇到的操作符比棧頂的操作符優先級高,比如把a + b * c。先創建空字符串作為后綴后達式,再從左到右掃描中綴表達式,把a放到新建后綴表達式后面,把+存到棧中,然后把b放到后綴表達式后面,這時遇到了*,*號的優先級比棧中的+高,也就是說,操作數b並不是+的第二個操作數,而是乘號的操作數,+的操作數要等待*的運算結果,這時把*放入到棧中,再把c放到后綴表達式中,中綴表達式掃描完畢,這時把操作符從棧中pop()出來,依次放到后綴表達式的后面,得到整個后綴表達式是abc*+

 

  遇到的操作符和棧頂操作符的優先級相等,但是從左向右結合,比如a-b+c。創建空字符串表示后綴表達式,ab放到空字符中,-放入到字符棧中,此時遇到+,+和-的優先級相等,+的操作要等它左邊表達式的結果,也就是說,要先算減的結果,a,b屬於-,所以把-彈棧,放到后綴表達式中,此時棧為空,再把+放入到棧中。把c放到后綴表達式,彈棧+,把+放到表達式中。最終,a-b+c的后綴表達式為ab-c+

   遇到的操作符和棧頂操作符的優先級相等,但是從右向左結合,比如a ^ b ^ c, 創建空字符串表示后綴表達式,ab放到空字符中,^放入到字符棧中,此時又遇到^,它和棧頂中的^優先級相等,但^是從右向左接合,要先計算后邊的結果,所以還是把^入棧,c放到后綴表達式,依次彈棧^,放到表達式中。最終,a ^ b ^ c的后綴表達式為a b c ^ ^

 

  綜上所述,中綴表達式轉化為后綴表達式,步驟如下:

  從左向右依次掃描中綴表達式,

    如果遇到操作數,就放入到后綴表達式字符串中,默認是空字符串。

    如果遇到^,就入字符棧。

    如果遇到+, -, *, /,  如果棧不為空並且新來的操作符比棧項的操作符優先級低,就不停彈棧,添加到后綴表達式中,然后把新的操作符入棧。

    如果遇到 (,入字符棧。

    如果遇到 ),依次彈字符棧,添加到后綴表達式中,直到遇到(,然后把它舍棄掉。

  掃描完畢后,如果字符棧不為空,再依次彈字符棧,添加到后綴表達式中。

import java.util.Stack;

public class InfixToPostfix {
    public static String convertToPostfix(String infixExpression){

        // 創建字符棧
        Stack<Character> operators = new Stack<>();

        // 創建將要實現的后綴表達式,初始為空
        StringBuilder postfix = new StringBuilder();

        for (int i = 0; i < infixExpression.length(); i++) {

            char c = infixExpression.charAt(i);

            // 如果中綴表達式中有空格
            if (c == ' ') {
                continue;
            } else if (c == '^'){
                operators.push(c);
            } else if (c == '+' || c == '-' || c == '*' || c == '/' ){
                while (!operators.isEmpty() && priority(c) <= priority(operators.peek())){
                    postfix.append(operators.pop());
                }

                operators.push(c);
            } else if (c == '('){
                operators.push(c);
            } else if(c == ')'){
                while (operators.peek() != '('){
                    postfix.append(operators.pop());
                }
                operators.pop();
            } else {
                postfix.append(c);
            }
        }

        while (!operators.isEmpty()){
            postfix.append(operators.pop());
        }

        return postfix.toString();

    }

    private static int priority(char operator) {
        if(operator == '*' || operator == '/' ) {
            return 1;
        } else if (operator == '+' || operator == '-' ) {
            return 0;
        } else {
            return -1;
        }
    }
}

  調用 convertToPostfix("a  / b  * (c  + (d  - e))"),得到后綴表達式為"a  / b  * (c  + (d  - e))"。 

 


免責聲明!

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



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