中綴表示式轉逆波蘭表示式,逆波蘭表示式的計算
阿新 • • 發佈:2020-07-17
中綴表示式轉字尾表示式:
1. 中綴表示式,是我們人可以識別的表示式形式;
2. 字尾表示式是計算機可以識別的表示式形式。
大體思路:
- 將中綴表示式的每一個符號存放在ArrayList a裡面
- 新建一個棧stack s來儲存中間符號,建立一個ArrayList b存放字尾表示式(為什麼不用棧呢?因為要將存入的字元遍歷,先進先出,用List更加方便)
- 掃描a:
- 如果是數字,直接放入b即可;
- 如果是符號:
- '(' : push到s中
- ')' : push棧s中的棧頂元素,依次存入b中,直到遇到'(',且這對括號可以被丟棄了
- 其他運算子:比較該運算子和s棧頂元素的優先順序,若它的優先順序高,則直接放入s中;若它的優先順序<=棧頂元素的優先順序,則將棧頂元素pop出來,存入b中,別忘了此時將該運算子繼續與s棧頂元素比較
public static List<String> parseSuffixExpressionList(List<String> list) { //定義兩個棧 Stack<String> s1 = new Stack<>(); //符號棧 //s2棧沒有pop操作,需要逆序輸出,如果用棧結構比較麻煩,所以可以用陣列實現 //Stack<String> s2 = new Stack<>(); // 儲存結果 ArrayList<String> s2 = new程式碼實現ArrayList<>(); //儲存結果 for (String ele : list) { //如果是一個數,則加入s2 if (ele.matches("\\d+")) { s2.add(ele); } else if (ele.equals("(")) { s1.push(ele); } else if (ele.equals(")")) { //如果是右括號,則依次彈出s1棧頂的運算子,並壓入s2,直到遇到左括號未知,且這對括號唄丟棄while (!s1.peek().equals("(")) { s2.add(s1.pop()); } //左括號被彈出(消除括號) s1.pop(); } else { //操作符的優先順序 //當ele的優先順序小於等於s1棧頂運算子,將s1棧頂的運算子彈出並加入到s2,再次將ele與新的棧頂運算子比較 while (s1.size() != 0 && Operation.getValue(ele) <= Operation.getValue(s1.peek())){ s2.add(s1.pop()); } s1.push(ele); } } //將s1中的剩餘的符號依次彈出並加入到s2; while (!s1.empty()){ s2.add(s1.pop()); } return s2; }
那下面寫如何計算逆波蘭表示式吧
//完成對逆波蘭表示式的運算 public static int calculate(List<String> list) { //建立棧 Stack<String> stack = new Stack<>(); //遍歷list for (String s : list) { if (s.matches("\\d+")) { //匹配是多位數 stack.push(s); } else { //pop出兩個數進行運算 int num2 = Integer.parseInt(stack.pop()); int num1 = Integer.parseInt(stack.pop()); int res = 0; //存放結果 if (s.equals("+")) { res = num1 + num2; } else if (s.equals("-")) { res = num1 - num2; } else if (s.equals("*")) { res = num1 * num2; } else if (s.equals("/")) { res = num1 / num2; } else { throw new RuntimeException("運算子有誤"); } stack.push(res + ""); } } //最後留在stack中的資料是結果 return Integer.parseInt(stack.pop()); }程式碼實現