結合性:當優先級相同時,看結合性,如果從左到右結合就是先算左邊的運算符,從右到左就是先算右邊的運算符。算法
優先級:誰優先級別高誰先運算ide
結合性列子:如a*b/c%d/e 由於運算符都是自左向右結合的因此 運算順序爲 ((((a*b)/c)%d)/e )函數
優先級:a/b-c+d*e-a*c -> ((((a/b)-c)+(d*e))-(a*c))post
(人習慣用)中綴表達式:二元運算符放在2個操做數的中間,書寫表達式的標準方式是中綴表達式spa
(編譯器用)後綴表達式:使用的是無括號的表達式code
如 blog
中綴表達式 後綴表達式token
2+3*4 234*+字符串
a*b+5 ab*5+get
(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個棧的實現參考前面的簡單棧的實現