1. 程式人生 > >Java集合框架練習-計算表示式的值

Java集合框架練習-計算表示式的值

最近在看《演算法》這本書,正好看到一個計算表示式的問題,於是就打算寫一下,也正好熟悉一下Java集合框架的使用,大致測試了一下,沒啥問題。

import java.util.*;
/*
 * 
 * 用來計算表示式
 * for example: 1+2*3*(4+3*1)-3*1+2+3/1;
 * (1+2*2-2*1*3*(1-1))*(1-2+3*(4+0));
 * 注意點:
 * 2.輸入的表達書不能還有空格,括號必須匹配
 * 基本思想:
 * 1.建立運算元棧以及操作符棧
 * 2.先去括號,每次遇到')'時,就退棧,直到遇到'('
 * 3.然後處理括號中的表示式,先處理優先順序高的,即*、/
 * 4.處理好高優先順序操作符之後,就處理+、-這種操作符
 * 5.對以上的運算結果入棧,繼續,處理完所有的(、)之後
 * 6.然後再次求一般的表示式即可
 */

public class CalExpression {
	
	private Stack<Double > vals = new Stack<Double >();
	private Stack<Character > ops = new Stack<Character >();
	
	public static void main(String[] args) {
		CalExpression obj = new CalExpression();
		obj.input();
	}
	
	public void input() {
		Scanner in =  new Scanner(System.in);
		while (in.hasNext()) {
			pushStack(in.next());
		}
	}
	
	public boolean check(char ch) {
		if (ch == '(' || ch == ')' || ch == '+' || ch == '-'
				|| ch == '*' || ch == '/') {
			return true;
		}
		return false;
	}
	
	
	public void pushStack(String str) {
		//匹配非數字,將(、)、+、-、*、/作為分隔符
		String[] strNum = str.split("[^0-9]"); 
	
		Queue<Double > que = new LinkedList<Double >();
		
		for (int i = 0; i < strNum.length; ++i) {
			if (!strNum[i].equals("")) {
				que.offer(Double.parseDouble(strNum[i]));
			}
		}
		
		boolean flag = false;
		for (int i = 0; i < str.length(); ++i) {
			if (check(str.charAt(i))) {
				//匹配到右括號,需要計算括號中的內容
				if (str.charAt(i) == ')') {
					Deque<Character > ops_tmp = new LinkedList<Character >();
					while (!ops.isEmpty() && ops.peek() != '(') {
						ops_tmp.offerFirst(ops.pop());
					}
					//'('退棧
					ops.pop();
					calExpress(ops_tmp);
				} else {
					ops.push(str.charAt(i));
				}
				flag = false;
				
			} else if (!flag) {
				vals.push(que.poll());
				flag = true;
			}
		}
		
		double value = getValue(vals.iterator(), ops.iterator());
		
		System.out.println(value);
		vals.clear();
		ops.clear();
		
	}
	
	
	public void calExpress(Deque<Character > deq_ops) {
		//運算元數目=操作符數目+1
		int numCount = deq_ops.size() + 1;
		
		Deque<Double > deq_num = new LinkedList<Double >();
		while (numCount > 0 && !vals.isEmpty()) {
			deq_num.offerFirst(vals.pop());
			numCount--;
		}
		
		double value = getValue(deq_num.iterator(), deq_ops.iterator());
		vals.push(value);
	}
	
	
	
	public double getValue(Iterator it_num, Iterator it_ops) {
		Deque<Double > vals = new LinkedList<Double >();
		Deque<Character > ops = new LinkedList<Character >();
		
		vals.offer((double)it_num.next());
		while (it_num.hasNext()) {
			char ch = (char)it_ops.next();
			if (ch == '+' || ch == '-') {
				vals.offer((double)it_num.next());
				ops.offer(ch);
			} else if (ch == '*' || ch == '/') {
				double num = vals.pollLast();
				if (ch == '*') {
					vals.offer(num * (double)it_num.next());
				} else {
					vals.offer(num / (double)it_num.next());
				}
			}
		}
		
		double value = vals.pollFirst();
		while (!vals.isEmpty() && !ops.isEmpty()) {
			if ((char)ops.pollFirst() == '+') {
				value += vals.pollFirst();
			} else {
				value -= vals.pollFirst();
			}
		}
		
		return value;
	}

}