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

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