1. 程式人生 > >資料結構Java實現——①棧-->棧的應用三、算術表示式求值

資料結構Java實現——①棧-->棧的應用三、算術表示式求值

package org.Stone6762.MStack.adopt;

import java.util.Scanner;

import org.Stone6762.MStack.imple.LinkStack;
/**
 * @author_Stone6762
 */
public class ArithExpEvaluation {

	/**
	 * @Describe_將原始的表示式轉換成一個字尾表示式
	 * @param expression原始的表示式
	 * @return與元素表示式相對於的字尾表示式
	 * @throws Exception
	 */
	public String conver2Postfix(String expression) throws Exception {
		LinkStack st = new LinkStack();// 運算子棧
		String postFix = "";// 字尾表示式
		for (int i = 0; expression != null && i < expression.length(); i++) {
			char c = expression.charAt(i);// 遍歷,如果是運算元,如果是操作符
			if (' ' != c) {// 字元不能為空
				if (isOpenParenthesis(c)) {// 左括號
					// 左括號就入棧
					st.push(c);
				} else if (isCloseParenthesis(c)) {// 右括號
					// 右括號就把所有的操作符出棧知道遇到一個左括號為止,然後將該左括號出棧並丟棄
					Character ac = (Character) st.pop();
					while (!isOpenParenthesis(ac)) {
						postFix += ac.toString();
						ac = (Character) st.pop();// 如果取出的是左括號,很顯然就丟棄了
					}
				} else if (isOperator(c)) {// 操作符
					/*
					 * 如果棧為空,直接進棧。 如果棧非空,則需要將棧頂運算子的優先順序和要入棧的運算子的優先順序進行比較
					 * 將棧中比要入棧的運算子優先順序高的運算子都出棧,然後將該運算子入棧
					 */
					if (!st.isEmpty()) { // 如果棧非空,則需要判斷
						Character ac = (Character) st.pop();
						while (ac != null
								&& priority(ac.charValue()) > priority(c)) {
							postFix += ac;
							ac = (Character) st.pop();
							// 因為是先取出來後判斷是,所以如果跳出迴圈 需要將最後一次取出的操作符壓入棧
						}
						// 將最後一次取出的優先順序低的運算子入棧
						if (ac != null) {
							st.push(ac);
						}
					}
					// 最後,將該運算子入棧
					st.push(c);
				} else {// 運算元,直接新增到字尾表示式 中
					postFix += c;
				}
			}
		}
		// 最後的時候,如果棧非空,則需要棧中的所有的運算子串聯到字尾表示式的末尾
		while (!st.isEmpty()) {
			postFix += st.pop().toString();
		}
		return postFix;
	}

	/** 
	 * @Describe_對字尾表示式進行運算
	 * @param postFix字尾表示式
	 * @return計算後的結果
	 * @throws Exception
	 */
	public double numberCalculate(String postFix) throws Exception {
		LinkStack st = new LinkStack();// 運算元棧
		for (int i = 0; i < postFix.length(); i++) {
			char c = postFix.charAt(i);
			if (isOperator(c)) {
				double d2 = Double.valueOf(st.pop().toString());
				double d1 = Double.valueOf(st.pop().toString());
				double d3 = 0;
				switch (c) {
				case '+':
					d3=d1+d2;
					break;
				case '-':
					d3=d1-d2;
					break;
				case '*':
					d3=d1*d2;
					break;
				case '/':
					d3=d1/d2;
					break;
				case '%':
					d3=d1%d2;
					break;
				case '^':
					d3=Math.pow(d1, d2);
					break;
				
				default:
					break;
				}
				
				st.push(d3);//將操作後的結果入棧
			}else{//當是運算元時,就直接進運算元棧
				st.push(c);
			}

		}

		return (double) st.pop();
	}

	/**
	 * @Describe_求運算子的優先順序
	 */
	private int priority(char c) {
		switch (c) {
		case '^':
			return 3;
		case '*':
		case '/':
		case '%':
			return 2;
		case '+':
		case '-':
			return 1;
		}
		return 0;
	}

	/** @Describe是否是一個操作符_
	 */
	private boolean isOperator(char c) {
		if ('+' == c || '-' == c || '*' == c || '/' == c || '^' == c
				|| '%' == c) {
			return true;
		}
		return false;
	}

	/** @Describe是否是一個右括號_
	 */
	private boolean isCloseParenthesis(char c) {
		return ')' == c;
	}

	/**@Describe_判斷是否是一個左括號
	 */
	private boolean isOpenParenthesis(char c) {
		return '(' == c;
	}

	public static void main(String[] args) throws Exception {
		
		ArithExpEvaluation p=new ArithExpEvaluation();
		Scanner scan = new Scanner(System.in);
		System.out.println("請輸入算術表示式:   ");
		while (scan.hasNext()) {
			String str=scan.next();
			String postFix=p.conver2Postfix(str);
			System.out.println("結果是:    "+p.numberCalculate(postFix));
			System.out.println();
			System.out.println("請輸入算術表示式:   ");
		}
		
	}
}