zoukankan      html  css  js  c++  java
  • 数据结构-栈的实现之运算式求值

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

    因为用到了两个栈(运算符栈和运算数栈)且这两个栈的基本存储类型还不一样,一个为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,"");
     79     while(*c != '#' || GetTop(OPTR) != '#')//结束条件指针c指向和运算符栈栈顶均为结束符#
     80     {
     81         if (!In(*c, OPSET)) //若是运算数则进运算数栈
     82         {
     83             Dr[0] = *c;
     84             Dr[1] = '';
     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,"");
     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函数就行了,注意调用的参数是字符串且要以#结束符结尾。

  • 相关阅读:
    路由器基础配置之ospf基础配置
    路由器基础配置之广播多路访问链路上的ospf
    路由器基础设置之ospf
    linux命令之文件系统权限操作常用命令
    路由器基础配置之路由重分布
    路由器配置 之 DHCP+DHCP中继服务配置
    路由器配置 之 PAP与CHAP认证
    基于链路的OSPF MD5口令认证
    压缩和归档操作(16个命令)
    基于链路的OSPF简单口令认证
  • 原文地址:https://www.cnblogs.com/ABook/p/5425867.html
Copyright © 2011-2022 走看看