用逆波蘭表示式實現表示式計算
阿新 • • 發佈:2019-01-13
表示式求值計算,如計算1+((2+3)*4)-5的值。
我的思路是先把表示式轉換為逆波蘭表示式,因為逆波蘭表示式更加符合計算機的處理邏輯,把表示式轉換為逆波蘭表示式的演算法如下:
- 初始化兩個棧:運算子棧s2和儲存中間結果的棧s1;
- 從左至右掃描中綴表示式;
- 遇到運算元時,將其壓s1;
- 遇到運算子時,比較其與s2棧頂運算子的優先順序:
- 如果s2為空,或棧頂運算子為左括號“(”,則直接將此運算子入棧;
- 否則,若優先順序比棧頂運算子的高,也將運算子壓入s2(注意轉換為字首表示式時是優先順序較高或相同,而這裡則不包括相同的情況);
- 否則,將s2棧頂的運算子彈出並壓入到s2中,再次轉到(4-1)與s2中新的棧頂運算子相比較;
- 遇到括號時:
- 如果是左括號“(”,則直接壓入s2;
- 如果是右括號“)”,則依次彈出s2棧頂的運算子,並壓入s1,直到遇到左括號為止,此時將這一對括號丟棄;
- 重複步驟2至5,直到表示式的最右邊;
- 將s2中剩餘的運算子依次彈出並壓入s1
字尾表示式求值的演算法如下:
首先定義一個棧:S3,在該棧中存放最終表示式的值。從左到右遍歷S1,然後按照如下規則操作S3:
(1)如果遇到的是數字,將數字壓入S3中;
(2)如果遇到單目運算子(運算物件只有一個的運算子,如:或(|)、與(&)等),取S3棧頂一個元素進行單目運算,將結果再次壓入S3中;
(3)如果遇到雙目運算子(運算物件有兩個的運算子,如:加(+)、賦值(=)等),取S3棧頂兩個元素(先出棧的在左,後出棧的在右)進行 雙目運算,將結果再次壓入S3中;
按照上面3條規則遍歷完S1,那麼最後S3中的值就是逆波蘭表示式的值了。
下面是我用java的程式碼實現
package com.sun.calculation; import java.util.LinkedList; import java.util.Queue; import java.util.Stack; /*** * 中綴表示式計算例如1+((2+3)*4)-5 * 實現思路就是先把中綴表示式轉換為逆波蘭表示式 * 然後再對逆波蘭表示式表示式進行計算 * @author swh * */ public class ExpressionComputation { /*** * 先把中綴表示式轉換為字尾表示式 * 再對字尾表示式進行計算 * @param expression 中綴表示式 * @return */ public static int computation(String expression) { return getRpnValue(getRpn(expression)); } /*** * 中綴表示式轉換為字尾表示式 * @param expression * @return */ private static Queue<Object> getRpn(String expression) { Queue<Object> valueQueue = new LinkedList<>(); Stack<String> optStack = new Stack<>(); String munStr = ""; for(int i=0;i<expression.length();i++) { char ch = expression.charAt(i); String str = String.valueOf(ch); if(ch>='0'&&ch<='9') { munStr +=str; }else { if(!munStr.equals("")) { valueQueue.add(Integer.valueOf(munStr)); munStr=""; } if (ch=='(') { optStack.push(str); }else if (ch==')') { while (optStack.size()!=0&&!optStack.peek().equals("(")) { valueQueue.add(optStack.pop()); } optStack.pop(); }else { while (optStack.size() != 0&&getOptionLevel(optStack.peek())>=getOptionLevel(str)) { valueQueue.add(optStack.pop()); } optStack.push(str); } } } valueQueue.add(Integer.valueOf(munStr)); while (optStack.size()!=0) { valueQueue.add(optStack.pop()); } return valueQueue; } /*** * 對字尾表示式進行計算 * @param valueQueue * @return */ public static int getRpnValue(Queue<Object> valueQueue) { Stack<Integer> numStack = new Stack<>(); while(!valueQueue.isEmpty()) { if(valueQueue.peek() instanceof Integer) { numStack.push((Integer)valueQueue.poll()); }else { String operation = (String)valueQueue.poll(); numStack.push(getOptionValue(operation, numStack.pop(), numStack.pop())); } } return numStack.pop(); } /*** * 得到運算子的優先順序 * @param opt */ public static int getOptionLevel(String operation) { int result = 0; switch (operation){ case "+": result=1; break; case "-": result=1; break; case "*": result=2; break; case "/": result=2; break; } return result; } /*** * 得到二元運算的值 * @param operation * @param b * @param a * @return */ public static int getOptionValue(String operation,int b,int a) { int result = 0; switch (operation){ case "+": result=a+b; break; case "-": result=a-b; break; case "*": result=a*b; break; case "/": result=a/b; break; } return result; } public static void main(String args[]) { computation("1+((2+3)*4)-5"); } }
參考了部落格: