標籤:system 用兩個棧 void pop 首碼運算式 電腦 row equals blog
中序運算式對我們而言是很直觀的(我們平時接觸的就是這個),但電腦處理起來比較麻煩(括弧、優先順序之類的),前序和後序運算式中沒有括弧,而且在計算中只需單向掃描,不需要考慮運算子的優先順序。如2*3/(2-1)+3*(4-1)
前序運算式就是首碼運算式,不含括弧的算術運算式,而且它是將運算子寫在前面,運算元寫在後面的運算式,例如:+/*23-21*3-4,也稱為“波蘭式”。
後序運算式與前序運算式掃描方式正好相反,例如:23*21-/341-*+。
用兩個棧實現中序運算式求值,運算式中只支援int( 但是計算的結果可能是float)
InfixExpr expr = new InfixExpr("2+3*4+5");
Assert.assertEquals(19, expr.evaluate(), 0.001f);
下面展示了在棧中具體的操作過程
下面是具體的實現代碼:
public class InfixExpr { String expr = null; public InfixExpr(String expr) { this.expr = expr; } public float evaluate() { char[] ch = expr.toCharArray(); MyStack stackOfTocken = new MyStack(); MyStack stackOfNumber = new MyStack(); for (int i = 0; i < ch.length; i++) { if (Character.isDigit(ch[i])) { int tmp = Integer.parseInt("" + ch[i]); while (i < ch.length - 1 && Character.isDigit(ch[++i])) { tmp = tmp * 10 + Integer.parseInt("" + ch[i]); } System.out.println(tmp); stackOfNumber.push(tmp); } if (ch[i] == ‘+‘ || ch[i] == ‘-‘ || ch[i] == ‘*‘ || ch[i] == ‘/‘) { stackOfTocken.push(ch[i]); } if (!(stackOfTocken.isEmpty()) && (char) stackOfTocken.peek() == ‘*‘) { int tmp = Integer.parseInt("" + ch[++i]); while (i < ch.length - 1 && Character.isDigit(ch[++i])) { tmp = tmp * 10 + Integer.parseInt("" + ch[i]); } if (i != ch.length - 1) { i--; } stackOfNumber.push(tmp); int tmp1 = Integer.parseInt("" + stackOfNumber.pop()); int tmp2 = Integer.parseInt("" + stackOfNumber.pop()); stackOfNumber.push(tmp1 * tmp2); stackOfTocken.pop(); } if (!(stackOfTocken.isEmpty()) && (char) stackOfTocken.peek() == ‘/‘) { int tmp = Integer.parseInt("" + ch[++i]); while (i < ch.length - 1 && Character.isDigit(ch[++i])) { tmp = tmp * 10 + Integer.parseInt("" + ch[i]); } if (i != ch.length - 1) { i--; } stackOfNumber.push(tmp); int tmp1 = Integer.parseInt("" + stackOfNumber.pop()); int tmp2 = Integer.parseInt("" + stackOfNumber.pop()); stackOfNumber.push(tmp2 / tmp1); stackOfTocken.pop(); } } // 將棧中的數字和運演算法逆置,便於計算 reverse(stackOfNumber); reverse(stackOfTocken); while (!(stackOfTocken.isEmpty())) { if ((char) stackOfTocken.peek() == ‘+‘) { int tmp1 = Integer.parseInt("" + stackOfNumber.pop()); int tmp2 = Integer.parseInt("" + stackOfNumber.pop()); stackOfNumber.push(tmp1 + tmp2); } if ((char) stackOfTocken.peek() == ‘-‘) { int tmp1 = Integer.parseInt("" + stackOfNumber.pop()); int tmp2 = Integer.parseInt("" + stackOfNumber.pop()); stackOfNumber.push(tmp1 - tmp2); } stackOfTocken.pop(); } return Float.parseFloat("" + stackOfNumber.pop()); } private void reverse(MyStack s) { if (s.isEmpty()) { return; } // 如果s裡面只有一個元素,就返回。具體實現是先pop出來一個,判斷剩下的是不是空棧。 Object tmp1 = s.pop(); reverse(s); if (s.isEmpty()) { s.push(tmp1); return; } Object temp2 = s.pop(); reverse(s); s.push(tmp1); reverse(s); s.push(temp2); }}
以及測試案例:
public class InfixExprTest { @Before public void setUp() throws Exception { } @After public void tearDown() throws Exception { } @Test public void testEvaluate() { // InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); { InfixExpr expr = new InfixExpr("2+3*4+5"); Assert.assertEquals(19.0, expr.evaluate(), 0.001f); } { InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); Assert.assertEquals(100.0, expr.evaluate(), 0.001f); } { InfixExpr expr = new InfixExpr("3*20/2"); Assert.assertEquals(30, expr.evaluate(), 0.001f); } { InfixExpr expr = new InfixExpr("20/2*3"); Assert.assertEquals(30, expr.evaluate(), 0.001f); } { InfixExpr expr = new InfixExpr("10-30+50"); Assert.assertEquals(30, expr.evaluate(), 0.001f); } }}
JAVA-棧實現中序運算式求值