1. 程式人生 > >棧的使用------Java實現中綴表示式轉為字尾表示式並計算

棧的使用------Java實現中綴表示式轉為字尾表示式並計算

轉換思路:

1、中綴表示式轉為字元陣列按順序遍歷

2、讀到運算元的時,新增到要輸出字串

3、讀到操作符是“(”,則直接把“(”壓入棧中。

4、讀到操作符“)”,則從棧中彈出棧元素並新增到要輸出的字串,直到遇到第一個“(”為止

5、讀到操作符“+”,“-”,若棧不為空且棧頂元素不是“(” 符號就彈棧中的資料,新增到要輸出的字串,否則就壓棧

6、讀到操作符“*”,“/”,若棧不為空且棧頂元素是“*”,“/”就從棧中彈出棧元素並輸出新增到要輸出字串,否則就壓棧

計算字尾表示式思路

1、字尾表示式轉為字元陣列按順序遍歷

2、若是數字就進行壓棧操作,若是運算元就彈出兩個進行運算

注意:用彈出的第二個數去操作(+ - * /)彈出的第一個數

程式碼實現

package com.zhl.dataStructure.stack;

import java.util.EmptyStackException;
import java.util.Stack;

/**
 * 
 * @author Administrator
 * 
 */
public class Postfix {
	/**
	 * 將字尾轉換為字尾表示式
	 * 
	 * @param infix
	 * @return
	 */
	public static String infixToPostfix(String infix) {
		// 操作符棧-----'+ - * / ( )'
		Stack<Character> op = new Stack<Character>();
		StringBuilder postfixStr = new StringBuilder("");
		char[] prefixs = infix.trim().toCharArray();
		Character ch;
		for (int i = 0; i < prefixs.length; i++) {
			ch = prefixs[i];
			// 如果是數字 0~9
			if (ch >= '0' && ch <= '9') {
				// vlaues.push(Integer.valueOf(ch));
				postfixStr.append(ch);
				continue;
			}
			// "("---直接壓棧
			if ('(' == ch) {
				op.push(ch);
				continue;
			}
			/*
			 * '+ - * /'----空棧直接壓棧否則與棧頂元素比較, 優先順序低於棧頂元素則彈出棧直到遇到優先順序相等或者低的就停止彈棧
			 * 最後將該操作符壓棧
			 */

			if ('+' == ch || '-' == ch) {
				// 只要棧不為空,棧頂元素不是'(' 就彈棧
				while (!op.empty() && (op.peek() != '(')) {
					postfixStr.append(op.pop());
				}
				op.push(ch);
				continue;
			}
			if ('*' == ch || '/' == ch) {
				// 只要棧不為空,棧頂元素是'* /' 就彈棧
				while (!op.empty() && (op.peek() == '*' || op.peek() == '/')) {
					postfixStr.append(op.pop());
				}
				op.push(ch);
				continue;
			}
			// ')'----開始彈棧直到遇到第一個'('
			if (')' == ch) {
				while (!op.empty() && op.peek() != '(') {
					postfixStr.append(op.pop());
				}
				op.pop();// ----將'('元素彈出
				continue;
			}
		}
		// 所有字元遍歷完畢運算元棧還有資料就全部彈棧
		while (!op.empty())
			postfixStr.append(op.pop());
		return postfixStr.toString();
	}

	/**
	 * 計算字尾表示式
	 * 
	 * @param postfix
	 * @return
	 */
	public static int sumPostfix(String postfix){
		//運算元棧---暫時只考慮正整數
		Stack<Integer> values;
		int result=0;
		try {
			values = new Stack<Integer>();
			 char [] postfixs =postfix.trim().toCharArray();
			 Character ch;
			 for(int i=0;i<postfixs.length;i++){
				 ch=postfixs[i];
				 if(ch >= '0' && ch <= '9') {
					 values.push(Integer.valueOf(String.valueOf(ch)));//---如操作棧
					 //或者:*****這樣更考驗思維
					 //values.push(Integer.valueOf(ch-'0'));
				 }else {
					 result=operate(ch, values.pop(),values.pop());
					 values.push(result);
					 
				 }
				  
			 }
			 result=values.pop();
			 if(!values.empty()){
				 throw  new Exception();
			 }
			
		} catch (NumberFormatException e) {
			System.out.println("資料轉換出異常");
		}catch(EmptyStackException e){//棧中為空還在進行彈棧操作
			System.out.println("字尾表示式格式有問題");
		}catch(Exception e){  // 符號都用完棧中還有多個數據
			System.out.println("字尾表示式格式有問題");
		}
		 return result;
	}
	public static int operate(char op,int value1,int value2){
		int result=0;
		//記住用第二個彈棧的值value2(加減乘除)第一個彈棧的值value1
		 switch ((int) op) {
		case 43://'+'
			result=value2+value1;
			break;
		case 45://'-'   
			result=value2-value1;
			break;
		case 42://'*'
			result=value2*value1;
			break;
		case 47://'/'
			result=value2/value1;
			break;
		default:
			break;
		}
		return result;
	}
	public static void main(String[] args) {
		String str="5+4*(3*(6-1*2+3))";
		System.out.println(str+":"+infixToPostfix(str));
		str=infixToPostfix(str);
		System.out.println("result:"+sumPostfix(str));
	}
	
	
}

測試結果: