棧與四則運算


上一篇也提到,棧其實是一種很重要的數據結構,下面簡單講解下棧是如何實現四則運算的。

在此之前,需要說明的是,很多編程語言在進行四則運算的時候,都不是直接運用中綴表達式進行運算的,一般會將中綴表達式轉換為后綴表達式然后利用棧進行具體的運算。因為,計算機無法識別所謂的先乘除后加減的運算順序的,而且,一旦出現括號的表達式,按照中綴表單時處理起來更困難,所以,一般來說,很多編程語言在進行四則運算的時候,都會講中綴轉換為后綴,因為,后綴(前綴也是)表達式有個很好的有點:它沒有括號,結合順序完全是按照符號出現的順序進行的,所以無需考慮過多的其他問題。

一、前綴、中綴以及后綴表達式的概念

  1、首先說中綴,它最簡單,就是我們平常寫的算式。1+2*3-(4-2),這個我們平常用的算式書寫方式就是中綴:中,代表符號是位於中間的,它進行和兩邊的數據進行結合並運算得出結果。

  2、后綴:符號位於兩個數字之后,例如:1+2的后綴表達式就是1 2+;1+2*3的后綴表達式就是:1(23*)+;如果理解不了,看下面的丑圖理解:

這里要注意的是:符號的結合順序是從最左邊那個符號(這里是*)進行結合的,例如:

123*-3+等價於2*3 - 1 + 3,具體看丑圖;同樣,前綴也遵循類似的原則,只不過它是從右往左結合(即最右邊的符號優先結合)

 

記住:2*3是顯式加上了括號的,為了方便理解,下面的式子涉及到乘除我也會自動為他們的運算加上括號。

  3、前綴:其實理解了后綴,前綴就很好理解了,前綴就是將符號放在數字的前面而已,結合的方式就是符號結合后面兩個數字,例子

  2*3 - 1 + 3的前綴表達式為:+-*2 3 1 3(最右邊符號優先結合);

 

二、中綴和后綴的轉換

  例如以下的中綴表達式:((2-(3*5))-(4/2));(注意,算法顯式加上括號)

  具體轉化的方法是:遇到數字,直接輸出;遇到左括號,直接忽略;遇到符號,將符號壓入棧,遇到右括號則彈出棧中的符號。

  ok,下面的代碼展示了這個過程:

//中綴表單時到后綴表達式的轉換
	public String change(String express){
		String rtn = "";
		char [] expressChar = express.toCharArray();
		Stack<Character> stack = new Stack<Character>();
		for(int i=0;i<expressChar.length;i++){
			if(expressChar[i]<='9' && expressChar[i]>='0'){
				//遇到數字,直接輸出
				rtn = rtn + expressChar[i];
			}else if(expressChar[i]=='*' || expressChar[i]=='-' || expressChar[i]=='+' || expressChar[i]=='/'){
				//遇到四則運算的符號,則直接壓入棧
				stack.push(expressChar[i]);
			}else if(expressChar[i]==')'){
				//如果是右括號,將棧中的元素pop出來
				rtn = rtn + stack.pop();
			}else{
				//其他元素則忽略(左括號)
				continue;
			}
		}
		return rtn;
	}

  當然,這種方法有一定的局限性:需要顯式地加上括號才可以轉換成功,所以忽略了一個步驟就是顯式為表達式加上必須的括號。不過這不是我們討論的主題,我們主要是用這個例子說明棧的一個典型作用罷了。

 

三、利用后綴表達式進行四則運算

  在三中,得到了四則運算式子的表達式之后,我們就可以運用棧進行四則運算了,而運算的方法是這樣:在后綴表達式中,我們遇到操作數,則將操作數推進棧中,遇到操作符,則從棧中推出兩個數字進行運算,並同時把運算結果推進棧中即可;循環以上步驟直到所有操作符以及操作數遍歷完畢。

下面簡單貼上該過程的代碼:

//利用后綴表達式進行四則運算
	public int operation(String suffix){
		char [] suffixChar = suffix.toCharArray();
		Stack<Character> stack = new Stack<Character>();
		for(int i=0;i<suffixChar.length;i++){
			if(suffixChar[i]<'9' && suffixChar[i]>'0'){
				stack.push(suffixChar[i]);
			}else {
				switch (suffixChar[i]) {
				case '+':
					stack.push((char)(stack.pop()-'0' + stack.pop()-'0'));
					break;
				case '-':
					stack.push((char)(stack.pop()-'0' - stack.pop()-'0'));
					break;
				case '*':
					stack.push((char)((stack.pop()-'0') * (stack.pop()-'0')));
					break;
				case '/':
					stack.push((char)((stack.pop()-'0') / (stack.pop()-'0')));
					break;
				}
			}
			
		}
		return stack.pop();
	}

  總而言之,棧是一個非常重要且基礎的數據結構,很多計算機編程語言底層其實就提供了棧的原始實現。例如,我們在嵌套調用函數(例如遞歸)時,就是一個典型的入棧出棧過程:先被調用的函數最后才結束運算;后被調用的函數后面執行,棧充當中間存儲數據和運算狀態的角色,保證運算正常運算下去。

  

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM