表达式求值-中缀表达式-后缀表达式

 

结合性:当优先级相同时,看结合性,如果从左到右结合就是先算左边的运算符,从右到左就是先算右边的运算符。算法

优先级:谁优先级别高谁先运算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个栈的实现参考前面的简单栈的实现