先看幾個中綴表達式和它們對應的后綴表達式的例子
可以看到操作數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))"。