利用棧Stack計算合法的算術表達式
限定的算術表達式求值問題:包含 “+”、“-”、“*”、“/” 、正整數和圓括號的合法算術表達式。
算術表達式轉化成后綴表達式
程序語言中,運算符在兩個運算數中間稱為中綴表達式,即我們常用的表達方法,例如 1+2*3。
在中綴表達式中要考慮運算的優先級,先乘除,后加減,從左到右,還有括號內先運算。
在后綴表達式中已經考慮了運算符的優先級,並且沒有括號,只有運算數和運算符。
例如上述例子 1+2*3 ,中綴表達式計算時,根據優先級,先計算2*3=6,再計算1+6=7
轉換成后綴表達式 1+2*3 => 123*+ ,
從左到右掃描第一個運算符為 * ,先執行2*3;第二個運算符為 + ,執行1+6.
中綴表達式轉后綴表達式過程
①初始化exp字符數組、resultExp字符數組(可變)、operator棧
exp字符數組:存放,合法的算術表達式
resultExp字符數組(可變):存放后綴表達式
operator棧:存放運算符,並將 “=” 作為棧底元素
②從exp讀取字符ch,若為運算數將后續運算數依次存放入resultExp中,並以#標志數值結束
③若ch為運算符,將其和operator棧頂中的運算符進行比較優先級比較
ch優先級大於棧頂運算符優先級,則ch進棧
ch優先級小於棧頂運算符優先級,則棧中運算符退棧,直至ch運算符大於棧頂運算符,ch再進棧。
ch優先級等於棧頂運算符優先級,特殊情況,只有括號滿足該情況,即“)”的優先級 等於“(”的優先級,將(退棧。
④exp掃描完畢,此時operator棧不空,則將 “=” 之前所有的運算符退棧並放入resultExp中
復雜一點的例子
(12-3)/(4+5)
算法如下:

package com.xumz.stack; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Stack; /** * 中綴表達式轉后綴表達式 * * @author xumz 2017/10/18 */ public class ExpressionChange { // 存放左運算符的優先級 Map<Character, Integer> leftOperator = new HashMap<Character, Integer>() { { put('=', 0); put('(', 1); put('+', 3); put('-', 3); put('*', 5); put('/', 5); put(')', 6); } }; // 存放右運算符的優先級 Map<Character, Integer> rightOperator = new HashMap<Character, Integer>() { { put('=', 0); put('(', 6); put('+', 2); put('-', 2); put('*', 4); put('/', 4); put(')', 1); } }; /** * 中綴轉后綴 * * @param str * @return */ public String trans(String str) { // 轉換成char[] char[] exp = str.toCharArray(); // 存放轉換結果 List<Character> resultExp = new ArrayList<Character>(); // 存放運算符,初始底為‘=’ Stack<Character> operator = new Stack<Character>(); operator.push('='); // 掃描exp表達式 int i = 0; while (i != exp.length) { // 數字情況 if (!isOperator(exp[i])) { while (i != exp.length && !isOperator(exp[i])) { resultExp.add(exp[i]); i++; } resultExp.add('#'); } // 運算符情況 else { switch (compareOperatorNice(operator.peek(), exp[i])) { case -1: operator.push(exp[i]); i++;// 繼續下一個字符 break; case 0: operator.pop(); i++;// 繼續下一個字符 break; case 1: resultExp.add(operator.peek()); operator.pop(); break; } } } while (!(operator.peek()=='=')) { resultExp.add(operator.peek()); operator.pop(); } // 轉換為String返回 return resultExp.toString(); } boolean isOperator(char ch) { if (leftOperator.containsKey(ch)) { return true; } return false; } /** * 比較左右運算符優先級,返回狀態結果 * * @param leftOperator * @param rightOperator * @return */ int compareOperatorNice(char left, char right) { if (leftOperator.get(left) == rightOperator.get(right)) { return 0; } if (leftOperator.get(left) < rightOperator.get(right)) { return -1; } return 1; } }