表達式求值-中綴表達式-后綴表達式


 

結合性:當優先級相同時,看結合性,若是從左到右結合就是先算左邊的運算符,從右到左就是先算右邊的運算符。

優先級:誰優先級別高誰先運算

結合性列子:如a*b/c%d/e  因為運算符都是自左向右結合的所以 運算順序為     ((((a*b)/c)%d)/e )

優先級:a/b-c+d*e-a*c     ->     ((((a/b)-c)+(d*e))-(a*c))

 

(人習慣用)中綴表達式:二元運算符放在2個操作數的中間,書寫表達式的標准方式是中綴表達式

(編譯器用)后綴表達式:使用的是無括號的表達式

如  

中綴表達式          后綴表達式

2+3*4            234*+

a*b+5            ab*5+

(1+2)*7           12+7*   

a/b*c            ab/c* 

((a/(b-c+d))*(e-a)*c      abc-d+/ea-*c*  

a/b-c+d*e-a*c        ab/c-de*+ac*-  

中綴表達式到后綴表達式的轉換(手工算法):

1.給每個表達式加上括號

2.將移動每個二元運算符,將其放在與其相應括號的右括號處 

3.刪除所有括號

如: 中綴表達式為:a/b-c+d*e-a*c

執行第一步:((((a/b)-c)+(d*e))-(a*c))

執行第二步:((((ab/)c-)(de*)+)(ac*)-) 

執行第三部:ab/c-de*+ac*-

后綴表達式為:ab/c-de*+ac*-

手工算法:計算機執行效率低,因為需要2遍掃描,第一遍掃描加括號,第二遍掃描移動運算符

計算機算法:

准備一個棧,操作數立即入棧,算法判斷優先級后入棧,優先級高的先入棧

即遇到操作數操作數就入棧,遇到算符先考慮優先級高的入棧。

 

中綴表達式轉換為后綴表達式函數

 1 #include<stdio.h>
 2 
 3 #define MAX_STACK_SIZE 100        //棧長度 
 4 #define MAX_EXPR_SIZE 100        //最大表達式長度 
 5 
 6 
 7 typedef enum{
 8     lparen,rparen,plus,minus,times,divide,mod,eos,operand
 9 } precedence;         //運算符定義 ()+-*、% 錯誤 運算數 
10 
11 precedence stack[MAX_STACK_SIZE];
12 static int isp[]={0,19,12,12,13,13,13,0};//()+-*/%eos的棧內優先級 
13 static int icp[]={20,19,12,12,13,13,13,0};//()+-*/%eos的引入            優先級
14 int stack[MAX_STACK_SIZE];
15 int expr[MAX_EXPR_SIZE];    //輸入字符串 
16 
17 void postfix(void)
18 {
19     /*
20     中綴式轉為后綴式 
21     */
22     char symbol;
23     precedence token;
24     int n=0;
25     int top=0;
26     stack[0]=eos;
27     for(token =get_token(symbol,&n); token!=eos;  token =get_token(symbol,&n)){
28         if(token==operand)                    //當時運算符直接輸出 
29             printf("%c");
30         else if(token==rparen){                //有括號的情景,當遇到右括號時,一直出棧到棧頂是左括號 
31             while(stack[top]!=lparen)
32                 printf(delete(&top));
33             delete(&top);
34         }
35         else{
36             while(isp[stack[top]]>=icp[token])//比較優先級
37                 printf(delete(&top));
38             add(&top,&token);
39         }     
40     }
41     while((token=delete(&top))!=eos)
42         prit_token(token);
43     printf("\n");
44 
45  } 

后綴式求值函數

 1 void postfix(void)
 2 {
 3     /*
 4     中綴式轉為后綴式 
 5     */
 6     char symbol;
 7     precedence token;
 8     int n=0;
 9     int top=0;
10     stack[0]=eos;
11     for(token =get_token(symbol,&n); token!=eos;  token =get_token(symbol,&n)){
12         if(token==operand)                    //當時運算符直接輸出 
13             printf("%c");
14         else if(token==rparen){                //有括號的情景,當遇到右括號時,一直出棧到棧頂是左括號 
15             while(stack[top]!=lparen)
16                 printf(delete(&top));
17             delete(&top);
18         }
19         else{
20             while(isp[stack[top]]>=icp[token])//比較優先級
21                 printf(delete(&top));
22             add(&top,&token);
23         }     
24     }
25     while((token=delete(&top))!=eos)
26         prit_token(token);
27     printf("\n");
28 
29  } 

獲取當前字符串的字符:

 1 precedence get_token(char *symbol,int *n)
 2 {
 3     /*
 4         從輸入字符串取出一個標記符號的函數 
 5         得到下一個字符給symbol,判斷后返回字符相應的值 
 6     */
 7     *symbol=expr[(*n)++];
 8     switch(*symbol){
 9         case '(': return lparen;
10         case ')': return rparen;
11         case '+': return plus;
12         case '-': return minus;
13         case '/': return divide;
14         case '*': return times;
15         case '%': return mod;    // 
16         case ' ': return eos;    //eos結束符號  
17         default : return operand;    //沒有錯誤檢查,默認是操作數 
18     }
19     
20 }

 

 precedence stackp[MAX_STACK_SIZE];

int stack[MAX_STACK_SIZE];

這2個棧的實現參考前面的簡單棧的實現

 


免責聲明!

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



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