数据结构-栈的实现之运算式求值

运算时求值核心思想:将运算式逐字符读取,若是运算数就进运算数栈,若是运算符就与运算符栈顶比较运算符的优先级来做相应的操作。直到遇到运算式的结束符且运算符栈里没有运算符为止。

因为用到了两个栈(运算符栈和运算数栈)且这两个栈的基本存储类型还不一样,一个为char类型存储运算符,而另一个为float类型存储数值的。所以就调用了两个栈的头文件Stack_Float.h和Stack_Char.h。两个头文件实现的基本操作是一样的,只是里面的结构体类型进行了改动。如下:

1 /*Stack_Char.h*/
2 typedef char CElemType;
3 typedef struct
4 {
5     CElemType data[MAXSIZE];
6     int top;                    
7 }StackChar;
1 /*Stack_Float.h*/
2 typedef float FElemType;
3 typedef struct
4 {
5     FElemType data[MAXSIZE];    
6     int top;                
7 }StackFloat;

还有栈的基本操作函数GetTop函数进行了改动。为了方便之后函数功能的实现,将数值参数去掉了,为了省事也去掉了对栈是否为空的判断,不管栈如何直接返回栈顶元素,容易出错。其他的基本函数与之前写的栈的顺序实现一样,记得将所有宏类型名称替换。GetTop函数如下以char类型为例:

 1 CElemType GetTop(StackChar S) 2 { 3 return S.data[S.top]; 4 } 

核心代码实现如下:

  1 #include "Stack_Float.h"
  2 #include "Stack_Char.h"
  3 #include "string.h"
  4 
  5 unsigned char Prior[7][7] = {     
  6     '>','>','<','<','<','>','>',
  7     '>','>','<','<','<','>','>',
  8     '>','>','>','>','<','>','>',
  9     '>','>','>','>','<','>','>',    
 10     '<','<','<','<','<','=',' ',
 11     '>','>','>','>',' ','>','>',
 12     '<','<','<','<','<',' ','='
 13 };        //算符间的优先关系,对应的实现关系在代码下面抛出
 14 
 15 #define OPSETSIZE 7
 16 char OPSET[OPSETSIZE]={'+' , '-' , '*' , '/' ,'(' , ')' , '#'};    //运算符集;运算符先支持+-*/,#为结束符
 17 
 18 //返回a与b的运算结果
 19 float Operate(float a, unsigned char theta, float b) 
 20 {
 21     switch(theta) 
 22     {
 23     case '+': 
 24         return a+b;
 25     case '-': 
 26         return a-b;
 27     case '*': 
 28         return a*b;
 29     case '/': 
 30         return a/b;
 31     default : 
 32         return 0;
 33     } 
 34 }    
 35 
 36 //判断Test字符是否在运算符集里
 37 Status In(char Test, char* TestOp) 
 38 {
 39     bool Find = false;
 40     for (int i = 0; i< OPSETSIZE; i++) 
 41     {
 42         if (Test == TestOp[i]) Find = true;
 43     }
 44     return Find;
 45 }
 46 
 47 //返回运算符在运算符集里的位置
 48 int ReturnOpOrd(char op,char* TestOp)
 49 {
 50     int i;
 51     for(i = 0; i < OPSETSIZE; i++) 
 52     {
 53         if (op == TestOp[i]) return i;
 54     }
 55     return 0;
 56 }
 57 
 58 //返回两个运算符的优先级
 59 char precede(char Aop, char Bop) 
 60 {
 61     return Prior[ReturnOpOrd(Aop,OPSET)][ReturnOpOrd(Bop,OPSET)];
 62 }
 63 
 64 //求解运算式
 65 float EvaluateExpression(char* MyExpression)
 66 {
 67     StackChar  OPTR;    // 运算符栈,字符元素
 68     StackFloat OPND;    // 运算数栈,实数元素
 69     char TempData[20];
 70     float Data,a,b;
 71     char theta,*c,x,Dr[2];
 72     /*初始化栈
 73     /*运算符栈先进栈一个#结束符做开始*/
 74     InitStack (OPTR);
 75     Push (OPTR, '#');
 76     InitStack (OPND);
 77     c = MyExpression;    //c指向求解的运算式
 78     strcpy_s(TempData,"\0");
 79     while(*c != '#' || GetTop(OPTR) != '#')//结束条件指针c指向和运算符栈栈顶均为结束符#
 80     {
 81         if (!In(*c, OPSET)) //若是运算数则进运算数栈
 82         {
 83             Dr[0] = *c;
 84             Dr[1] = '\0';
 85             strcat_s(TempData,Dr);
 86             c++;
 87             if(In(*c,OPSET)) 
 88             {
 89                 Data = (float)atof(TempData);//将char类型值转换成float型数值
 90                 Push(OPND, Data);
 91                 strcpy_s(TempData,"\0");
 92             }
 93         }
 94         else  //不是运算数则进运算符栈
 95         {  
 96             switch (precede(GetTop(OPTR), *c))
 97             { 
 98             case '<':   // 栈顶元素优先权低
 99                 Push(OPTR, *c);
100                 c++;
101                 break;
102             case '=':   // 脱括号并接收下一字符
103                 Pop(OPTR, x);   
104                 c++;
105                 break;
106             case '>':   // 退栈并将运算结果入栈
107                 Pop(OPTR, theta);
108                 Pop(OPND, b);
109                 Pop(OPND, a);                   
110                 Push(OPND, Operate(a, theta, b)); 
111                 break;
112             }
113         }
114     }
115     return GetTop(OPND);
116 }

其中Prior二维数组作用为判断运算符优先级。实现表:

   +  -  *  /  (   )  #
+ > > <  < <  >  >
-  > > <  < <  >  >
*  >>  >  > <  >  >
/  > > >  >  < >  >
(  < < <  <  < =
)  > > >  >     >   >
# < < <  <  <      =

对不齐咳咳咳 。

支持的运算有:+、-、*、/、();

测试数据直接printf输出EvaluateExpression函数就行了,注意调用的参数是字符串且要以#结束符结尾。

 

posted @ 2016-04-23 22:20  A_book  阅读(2110)  评论(0编辑  收藏  举报