轉載請註明出處:http://www.cnblogs.com/luna-lovegood/archive/2012/07/17/2596501.html
一個算術表達式,含有數字(爲簡化處理,數字只有一位),運算符:+、-、*,以及括號,求表達式的值。
給出的表達式是一般我們見到的中綴表達式,即運算符位於操作數之間。如果把中綴表達式轉化爲後綴表達式,那麼對後綴表達式求值將會很方便。
後綴表達式特點:
1.操作符位於操作數之後;
2.沒有括號;
3.運算符沒有優先級。
中綴表達式轉化爲後綴表達式的步驟:(還有一種方法:寫成二叉樹的形式,進行後序遍歷爲後綴表達式,中序表達式爲中綴表達式)
1.初始化一個空操作符棧和空結果字符串;
2.從前到後讀取中綴表達式的字符,如果是操作數,加到結果字符串後面;
3.如果是操作符,分兩種情況入棧:
a.如果待入棧操作符優先級大於棧頂操作符,直接入棧;
b.如果待入棧操作符優先級小於或等於棧頂操作符,棧頂操作符加到結果字符串後面;重複b過程直到遇到前括號‘(’或棧頂操作符優先級比待入棧操作符小,待入棧操作符入棧。
4.如果是前括號‘(’,直接入棧;
5.如果是後括號,將棧中操作符依次彈出,直至遇到一個前括號‘(’結束。前括號出棧。
最後結果字符串就是後綴表達式。
後綴表達式求值的步驟:
1.初始化一個空操作數棧;
2.從前到後讀取後綴表達式字符。如果是操作數直接入棧。如果讀到一個操作符@,彈出棧頂元素a和新的棧頂元素b,執行b @ a,將結果壓入棧中;
3.最後棧中只剩下一個元素,即表達式的值。
關於中綴表達式轉換成後綴表達式與後綴表達式正確性的說明:
先觀察一些例子:
1.假設中綴表達式沒有括號,且所有運算符優先級相同。比如a+b-c+d-e+f ,將被轉化爲ab+c-d+e-f+。此時用括號來說明後綴表達式執行順序:((((( ab+ ) c- ) d+ ) d- ) f+ ),運算順序沒有改變。
2.假設中綴表達式沒有括號,但是運算符優先級不同。比如a+b*c+d-e*f,將被轉化爲 abc*+d+ef*-,用括號來說明後綴表達式執行順序:((( a ( bc* ) + ) d+ ) ( ef* ) - ),運算順序依然沒有變。
3.假設中綴表達式有括號。比如(a+b)*(c+d)*e+f,將被轉化爲ab+cd+*e*f+,用括號表示執行順序(((( ab+ ) ( cd+ ) * ) e* ) f+ )。運算順序還是沒有改變。
不難觀察出以下5點:
1.後綴表達式中操作數出現的順序和中綴表達式一樣。這是因爲操作數是直接加入結果字符串;
2.每個操作符都會入棧一次,出棧一次;
3.在沒有括號時,如果相鄰兩個操作符優先級相同或前一個操作符的優先級高,則後綴表達式中操作符出現的順序和中綴表達式一樣。因爲後一個操作符入棧時,棧頂元素一定是前一個相鄰的操作符,如果其優先級小於等於待入棧的,則前一個操作符被彈出並加入結果字符串,後綴表達式中操作符順序得到保持。
4.在沒有括號時,如果相鄰兩個操作符,後者優先級大與前者,後者將直接被壓入棧中,且位於前者之上。在出棧時,後者將先出棧,因而後綴表達式中,操作符順序發生交換,即中綴表達式中要先運算的操作在後綴表達式中出現在前面。
5.出現括號。括號中的處理因爲遵循前4點,不再贅述,而括號的內容作爲一個整體的性質得到維護。
參考文章:
http://blog.csdn.net/daheiantian/article/details/6553713
http://blog.csdn.net/niushuai666/article/details/6702964
http://www.cnblogs.com/luna-lovegood/archive/2012/07/17/2596464.html
代碼:
1 //zzy2012.7.17 2 //利用後綴表達式對算數表達式求值 3 //不含符號變量處理,且數字都是一位,運算符僅含+、-、*和括號 4 #include<cstdio> 5 #include<iostream> 6 #include<cstring> 7 #define NUM 200 8 9 using namespace std; 10 11 char s[NUM],a[NUM],stack[NUM]; 12 int stacknum[NUM]; 13 14 int trans(char s[NUM],char a[NUM],char stack[NUM],int lens){ 15 int lena = 0,top = 0; 16 for(int i=0; i<lens; i++){ 17 if(s[i]>='0' && s[i]<='9'){ 18 a[lena++] = s[i]; 19 } 20 else if(s[i]=='+' || s[i]=='-'){ 21 while(top>0 && stack[top-1]!='(') 22 a[lena++] = stack[--top]; 23 stack[top++] = s[i]; 24 } 25 else if(s[i] == '*'){ 26 while(top>0 && stack[top-1]!='(' && stack[top-1]!='+' && stack[top-1]!='-') 27 a[lena++] = stack[--top]; 28 stack[top++] = s[i]; 29 } 30 else if(s[i]=='(') 31 stack[top++] = s[i]; 32 else if(s[i]==')'){ 33 while(top>0 && stack[top-1]!='(') 34 a[lena++] = stack[--top]; 35 top--; 36 } 37 } 38 while(top>0){ 39 a[lena++] = stack[--top]; 40 } 41 return lena; 42 } 43 44 int calcu(char a[NUM],int stack[NUM],int lena){ 45 int top=0; 46 for(int i=0; i<lena; i++) 47 if(a[i]>='0' && a[i]<='9') 48 stack[top++] = a[i]-'0'; 49 else{ 50 if(a[i]=='+') 51 stack[top-2] = stack[top-2] + stack[top-1]; 52 else if(a[i] == '-') 53 stack[top-2] = stack[top-2] - stack[top-1]; 54 else if(a[i]=='*') 55 stack[top-2] = stack[top-2] * stack[top-1]; 56 top--; 57 } 58 return stack[0]; 59 } 60 61 int main() 62 { 63 int ans,lens,lena; 64 gets(s); 65 lens = strlen(s); 66 lena = trans(s,a,stack,lens);//將中綴表達式轉換橫後綴表達式,返回值是後綴表達式a的長度 67 ans = calcu(a,stacknum,lena);//計算後綴表達式值 68 printf("%d\n",ans); 69 return 0; 70 }