数据结构(19)栈典型问题之C++实现表达式求值

导言

表达式求值是程序设计语言中的一个最基本问题。本次实现采取“算符优先法”。

表达式求值

如何一个表达式都是由操作数、运算符和界限符组成的,我们称为单词。一般地,操作数既可以是常数也可以是被说明为变量或常量的标识符;运算符可以分为算术运算符、关系运算符和逻辑运算符3类;基本界限符有左右括号和表达式结束符等。

我们把运算符和界限符统称为算符它们构成的集合命名为OP。

我们得到任意的两个相继出现的算符 θ1 θ2 只记得优先级关系至多是下面3种关系之一;
θ1<θ2 : θ1 的优先权低于 θ2
θ1=θ2 : θ1 的优先权等于 θ2
θ1>θ2 : θ1 的优先权高于 θ2

算符优先关系表
这里写图片描述

为实现算法优先算法,可以设置两个工作栈。一个称为OPTR,用以寄存运算符;另一个称为OPND,用以寄存操作数或运算结果。算法基本思路:
1、首先置操作数栈为空栈,表达式起始符”#”为运算符栈的栈底元素;
2、依次读入表达式中的每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈的栈顶运算比较优先权后做相应的操作,直到表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为“#”)。

算法

#define OPSETSIZE 7
unsigned char Prior[7][7] = {     // 表3.1  算符间的优先关系
      '>','>','<','<','<','>','>',
      '>','>','<','<','<','>','>',
      '>','>','>','>','<','>','>',
      '>','>','>','>','<','>','>',  
      '<','<','<','<','<','=',' ',
      '>','>','>','>',' ','>','>',
      '<','<','<','<','<',' ','='
};      
float Operate(float a, unsigned char theta, float b);
char OPSET[OPSETSIZE]={'+' , '-' , '*' , '/' ,'(' , ')' , '#'};
Status In(char Test,char* TestOp);
char precede(char Aop, char Bop);

float EvaluateExpression(char* MyExpression) {  // 算法3.4
   // 算术表达式求值的算符优先算法。
   // 设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合。
   StackChar  OPTR;    // 运算符栈,字符元素
   StackFloat OPND;    // 运算数栈,实数元素
   char TempData[20];
   float Data,a,b;
   char theta,*c,x,Dr[2];

   InitStack (OPTR);
   Push (OPTR, '#');
   InitStack (OPND);
   c = MyExpression;
   strcpy(TempData,"\0");
   while (*c!= '#' || GetTop(OPTR)!= '#') {
      if (!In(*c, OPSET)) {
         Dr[0]=*c;
         Dr[1]='\0';
         strcat(TempData,Dr);
         c++;
         if(In(*c,OPSET)) {
            Data=(float)atof(TempData);
            Push(OPND, Data);
            strcpy(TempData,"\0");
         }
      } else {   // 不是运算符则进栈
         switch (precede(GetTop(OPTR), *c)) { 
            case '<':   // 栈顶元素优先权低
                 Push(OPTR, *c);  
                 c++;
                 break;
            case '=':   // 脱括号并接收下一字符
                 Pop(OPTR, x);   
                 c++;
                 break;
            case '>':   // 退栈并将运算结果入栈
                 Pop(OPTR, theta);
                 Pop(OPND, b);  
                 Pop(OPND, a);                      
                 Push(OPND, Operate(a, theta, b)); 
                 break;
         } // switch
      }
   } // while
   return GetTop(OPND);
} // EvaluateExpression

float Operate(float a,unsigned char theta, float b) {
   switch(theta) {
      case '+': return a+b;
      case '-': return a-b;
      case '*': return a*b;
      case '/': return a/b;
      default : return 0;
   } 
}   

Status In(char Test,char* TestOp) {
   bool Find=false;
   for (int i=0; i< OPSETSIZE; i++) {
      if (Test == TestOp[i]) Find= true;
   }
   return Find;
}


int ReturnOpOrd(char op,char* TestOp) {
   int i;
   for(i=0; i< OPSETSIZE; i++) {
      if (op == TestOp[i]) return i;
   }
   return 0;
}

char precede(char Aop, char Bop) {
   return Prior[ReturnOpOrd(Aop,OPSET)][ReturnOpOrd(Bop,OPSET)];
}

算法具体实现

参考下面的文档即可
表达式求值实验报告-星空奇人

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YuYunTan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值