(七)中綴表達式轉換後綴表達式算法

表達式的三種形式

中綴表達式:運算符放在兩個運算對象中間,如:(2+1)*3
後綴表達式:不包含括號,運算符放在兩個運算對象的後面,所有的計算按運算符出現的順序,嚴格從左向右進行(不再考慮運算符的優先規則,如:21 + 3 *
前綴表達式:同後綴表達式一樣,不包含括號,運算符放在兩個運算對象的前面,如:*+ 2 1 3 
表達式的轉換
將中綴表達式轉換爲後綴表達式:

(1)當讀到數字直接送至輸出隊列中;

(2)當讀到運算符t時:

    a.將棧中所有優先級高於或等於t的運算符彈出,送到輸出隊列中;

  這句話不好理解,可以說成這樣,從棧頂開始,依次彈出比當前處理的運算符優先級高的運算符,直到一個比它優先級低的或者遇到了一個左括號就停止。

    b.t進棧;

(3)讀到左括號時總是將它壓入棧中;

(4)讀到右括號時,將靠近棧頂的第一個左括號上面的運算符全部依次彈出,送至輸出隊列後,再丟棄左括號;

(5)中綴表達式全部讀完後,若棧中仍有運算符,將其送到輸出隊列中。

中綴表達式:3+(2-5)*6/3轉換爲後綴表達式的過程:

後綴表達式              棧

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)*6/3=-3,其後綴表達式爲:325-6*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;
	}
}



發佈了31 篇原創文章 · 獲贊 3 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章