表達式求值——棧的應用

 

轉載請註明出處: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 }
複製代碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章