表達式的三種形式
(1)當讀到數字直接送至輸出隊列中;
(2)當讀到運算符t時:
a.將棧中所有優先級高於或等於t的運算符彈出,送到輸出隊列中;
這句話不好理解,可以說成這樣,從棧頂開始,依次彈出比當前處理的運算符優先級高的運算符,直到一個比它優先級低的或者遇到了一個左括號就停止。
b.t進棧;
(3)讀到左括號時總是將它壓入棧中;
(4)讀到右括號時,將靠近棧頂的第一個左括號上面的運算符全部依次彈出,送至輸出隊列後,再丟棄左括號;
(5)中綴表達式全部讀完後,若棧中仍有運算符,將其送到輸出隊列中。
後綴表達式 棧
3
3 +
3 +(
32 +(
32 +(-
325 +(-
325- +
325- +*
325-6 +*
325-6* +/
325-6*3 +/
325-6*3/+
最終後綴表達式爲:325-6*3/+
(1)建立一個棧S;
(2)從左到右讀後綴表達式,讀到數字就將它轉換爲數值壓入棧S中,讀到運算符則從棧中依次彈出兩個數分別到Y和X,然後以“X 運算符Y”的形式計算機出結果,再壓加棧S中;
(3)如果後綴表達式未讀完,就重複上面過程,最後輸出棧頂的數值則爲結束。
棧 運算
3 2 5 325入棧
3 2-5=-3
3 -3 運算結果進棧
3 -3 6
3 -3*6=-18
3 -18 3 -18/3=-6
3 -6 3+(-6)=-3
-3
import java.util.Stack;
import java.util.regex.*;
public class StringToArithmetic {
private StringToArithmetic() {
}
/**
* 給出一個算術表達式,返回結果。 例如 (5+8+10)*1,返回23
*
* @param string
*/
public static double stringToArithmetic(String string) {
return suffixToArithmetic(infixToSuffix(string));
}
/**
* 中綴表達式轉後綴表達式 只處理了+,-,*,/和括號,沒有處理負號及其它運算符,也沒對前綴表達式驗證。
* 如要處理負號,可對表達式進行預轉義處理,當下麪條件成立時,將負號換成單目運算符"!" infix.charAt[i]=='-'&&(
* i==0||infix.charAt[i-1]=='(')
* 3*6/4+3
* 3+6-4 3 6 + 4 -
* 3+(6-4/2)*5 3 6 4 2 / - 5 * +
*/
public static String infixToSuffix(String infix) {
Stack<Character> stack = new Stack<Character>();
String suffix = "";
int length = infix.length();
for (int i = 0; i < length; i++) {
Character temp;
char c = infix.charAt(i);
switch (c) {
// 忽略空格
case ' ':
break;
// 碰到'(',push到棧
case '(':
stack.push(c);
break;
// 碰到'+''-',將棧中所有運算符彈出,送到輸出隊列中
case '+':
case '-':
while (stack.size() != 0) {
temp = stack.pop();
if (temp == '(') {
stack.push('(');
break;
}
suffix += " " + temp;
}
stack.push(c);
suffix += " ";
break;
// 碰到'*''/',將棧中所有乘除運算符彈出,送到輸出隊列中
case '*':
case '/':
while (stack.size() != 0) {
temp = stack.pop();
if (temp == '(' || temp == '+' || temp == '-') {
stack.push(temp);
break;
} else {
suffix += " " + temp;
}
}
stack.push(c);
suffix += " ";
break;
// 碰到右括號,將靠近棧頂的第一個左括號上面的運算符全部依次彈出,送至輸出隊列後,再丟棄左括號
case ')':
while (stack.size() != 0) {
temp = stack.pop();
if (temp == '(')
break;
else
suffix += " " + temp;
}
// suffix += " ";
break;
//如果是數字,直接送至輸出序列
default:
suffix += c;
}
}
//如果棧不爲空,把剩餘的運算符依次彈出,送至輸出序列。
while (stack.size() != 0)
{
suffix += " " + stack.pop();
}
return suffix;
}
/**
* 通過後綴表達式求出算術結果
*
* @param String
* postfix
* @return double
*/
public static double suffixToArithmetic(String postfix) {
Pattern pattern = Pattern.compile("\\d+||(\\d+\\.\\d+)"); //使用正則表達式 匹配數字
String strings[] = postfix.split(" ");
for (int i = 0; i < strings.length; i++)
strings[i].trim();
Stack<Double> stack = new Stack<Double>();
for (int i = 0; i < strings.length; i++) {
if (strings[i].equals(""))
continue;
//如果是數字,則進棧
if ((pattern.matcher(strings[i])).matches()) {
stack.push(Double.parseDouble(strings[i]));
} else {
//如果是運算符,彈出運算數,計算結果。
double y = stack.pop();
double x = stack.pop();
stack.push(caculate(x, y, strings[i])); //將運算結果重新壓入棧。
}
}
return stack.pop(); //彈出棧頂元素就是運算最終結果。
}
private static double caculate(double x, double y, String simble) {
if (simble.trim().equals("+"))
return x + y;
if (simble.trim().equals("-"))
return x - y;
if (simble.trim().equals("*"))
return x * y;
if (simble.trim().equals("/"))
return x / y;
return 0;
}
}