java中綴表達式轉後綴表達式

將中綴表達式轉換爲後綴表達式
與轉換爲前綴表達式相似,遵循以下步驟:
(1) 初始化兩個棧:運算符棧S1和儲存中間結果的棧S2;
(2) 從左至右掃描中綴表達式;
(3) 遇到操作數時,將其壓入S2;
(4) 遇到運算符時,比較其與S1棧頂運算符的優先級:
(4-1) 如果S1爲空,或棧頂運算符爲左括號“(”,則直接將此運算符入棧;
(4-2) 否則,若優先級比棧頂運算符的高,也將運算符壓入S1(注意轉換爲前綴表達式時是優先級較高或相同,而這裏則不包括相同的情況);
(4-3) 否則,將S1棧頂的運算符彈出並壓入到S2中,再次轉到(4-1)與S1中新的棧頂運算符相比較;
(5) 遇到括號時:
(5-1) 如果是左括號“(”,則直接壓入S1;
(5-2) 如果是右括號“)”,則依次彈出S1棧頂的運算符,並壓入S2,直到遇到左括號爲止,此時將這一對括號丟棄;
(6) 重複步驟(2)至(5),直到表達式的最右邊;
(7) 將S1中剩餘的運算符依次彈出並壓入S2;

(8) 依次彈出S2中的元素並輸出,結果的逆序即爲中綴表達式對應的後綴表達式(轉換爲前綴表達式時不用逆序)。

import java.util.Stack;

public class Calculator {

	public static void main(String[] args) {
		suffixCalc("1+((2+3)*4)-5");
	}
	public static void suffixCalc(String input) {
		Stack<Double> numbersStack = new Stack<Double>();
		Stack<Character> operatorsStack = new Stack<Character>();
		Stack<Object> suffixExpr = new Stack<Object>();
		int len = input.length();
		char c, temp;
		double number;
		for (int i = 0; i < len; i++) {
			c = input.charAt(i);
			if (Character.isDigit(c)) {
				int endDigitPos = getEndPosOfDigit(input, i);
				number = Double.parseDouble(input.substring(i, endDigitPos));
				i = endDigitPos - 1;
				numbersStack.push(number);
				if ((int)number == number) {
					suffixExpr.push((int)number);
				} else {
					suffixExpr.push(number);
				}
			} else if (isOperator(c)) {
				// 操作符棧非空,且棧頂不是'(',且當前操作符優先級低於棧頂操作符
				while (!operatorsStack.isEmpty() 
						&& operatorsStack.peek() != '(' 
						&& priorityCompare(c, operatorsStack.peek()) <= 0) {
					suffixExpr.push(operatorsStack.peek());
					numbersStack.push(calc(numbersStack, operatorsStack.pop()));
				}
				operatorsStack.push(c);
			} else if (c == '(') {
				operatorsStack.push(c);
			} else if (c == ')') {
				while ((temp = operatorsStack.pop()) != '(') {
					numbersStack.push(calc(numbersStack, temp));
					suffixExpr.push(temp);
				}
			} else if (c == ' ') {
				
			} else {
				throw new IllegalArgumentException("wrong character '" + c + "'");
			}
		}
		
		while (!operatorsStack.isEmpty()) {
			temp = operatorsStack.pop();
			suffixExpr.push(temp);
			numbersStack.push(calc(numbersStack, temp));
		}
		
		printStack(suffixExpr);
		System.out.println("\ncalc result\t" + numbersStack.pop());
	}
	
	private static void printStack(Stack<?> stack) {
		String s = "";
		while (!stack.isEmpty()) {
			s += stack.pop();
		}
		for (int i = s.length()-1; i >= 0; i--) {
			System.out.print(s.charAt(i)+" ");
		}
	}

	private static int getEndPosOfDigit(String input, int start) {
		char c;
		int end = start + 1;
		for (int i = start + 1; i < input.length(); i++) {
			c = input.charAt(i);
			if (Character.isDigit(c) || c == '.') {
				continue;
			} else {
				end = i;
				break;
			}
		}
		return end;
	}

	private static boolean isOperator(char c) {
		return (c == '+' || c == '-' || c == '*' || c == '/');
	}

	// op1優先級高於op2 return 1
	private static int priorityCompare(char op1, char op2) {
		switch (op1) {
		case '+':
		case '-':
			return (op2 == '*' || op2 == '/' ? -1 : 0);
		case '*':
		case '/':
			return (op2 == '+' || op2 == '-' ? 1 : 0);
		}
		return 1;
	}

	private static double calc(Stack<Double> numbersStack, char op) {
		double num1 = numbersStack.pop();
		double num2 = numbersStack.pop();
		return calc(num2, num1, op);
	} 
	private static double calc(double num1, double num2, char op) throws IllegalArgumentException {
		switch (op) {
		case '+':
			return num1 + num2;
		case '-':
			return num1 - num2;
		case '*':
			return num1 * num2;
		case '/':
			if (num2 == 0)
				throw new IllegalArgumentException("divisor can't be 0.");
			return num1 / num2;
		default:
			return 0;
		}
	}
}

output:

1 2 3 + 4 * + 5 - 
calc result 16.0

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章