11、数据结构笔记之十一栈的应用之表达式求值实现

11、数据结构笔记之十一栈的应用之表达式求值实现

           “人生不售来回票,一旦动身,绝不能复返。

           继续栈应用实现

 

1.  表达式求值

表达式求值是设计语言编译中的一个基本问题,它的实现是栈应用的又一个典型例子。

任何一个表达式都是由操作数(Operand)、运算符(operator)和界限符(delimiter)组成。

           操作数可以是常数也可以是变量或变量的标识符。

           运算符可以分为算术运算符、关系运算符和逻辑运算符三类。

           界限符有左右括号和表达式结束符。

几个算术四则运算的规则:

n  先乘除,后加减;

n  从左算到右

n  先括号内,后括号外

此处实现,假定不出现语法错误,否则过于复杂,蛤蟆也不能理解了。

2.  运算符优先级

对于连个相继出现的操作符θ1和θ2 有三种关系:大于、等于和小于。由此可以列出“+-*/”之间的优先级。如下表:

 

+

-

*

/

(

)

#

+

-

*

/

(

=

 

)

 

#

 

=

 

加减乘除优先性都低于“(”但是高于“)”,由运算从左到右可知,当θ1=θ2 ,令θ1>θ2

为了算法简洁,在表达式的左边和右边虚设一个“#”,这一对“#”表示一个表达式求值完成。

“(”=“)”当一对括号相遇时表示括号内已运算完成。

“)”和“(”、“#”和“(”、“(”和“#”无法相继出现如果出现则表达式出现语法错误。

为实现优先算法,可以使用两个工作栈,一个是OPTR,用于寄存运算符,一个是OPND,用于寄存运算数和运算结果。

3.  算法基本思路

l  首先置操作数栈为空栈,表达式起始符为“#”为栈底元素。

l  依次读入表达式中的每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先权作相应操作,直至整个表达式求值完毕(OPTR栈顶元素和当前读入的字符均为“#”)。

 

 

4.  求值函数EvaluateExpression实现

根据算法基本思路,代码实现如下:

int EvaluateExpression(){

           intflag;

           charc;

           charx,theta;

           chara,b;

 

           charOP[]="+-*/()#";

           SqStack  OPTR;

           SqStack  OPND;

 

           InitStack(&OPTR);     

           Push(&OPTR,'#');

           InitStack(&OPND);

           flag=getNext(&c);

 

           GetTop(OPTR,&x);

           while(c!='#'|| x != '#')

           {

                     if(flag== 0)

                     {

                                Push(&OPND,c);

                                flag= getNext(&c);

                     }       

                     else

                     {

                                GetTop(OPTR,&x);

                                switch(Precede(x,c))

                                {

                                case'<'://栈顶元素优先级低                   

                                          Push(&OPTR,c);

                                          flag= getNext(&c);

                                          break;

                                case'='://脱括号并接受下一字符

                                          Pop(&OPTR,&x);

                                          flag= getNext(&c);

                                          break;

                                case'>'://退栈并将运算结果入栈                                      

                                          Pop(&OPTR,&theta);

                                          Pop(&OPND,&b);

                                          Pop(&OPND,&a);

                                          Push(&OPND,Operate(a, theta, b));

                                          break;

                                }

                     }

                     GetTop(OPTR,&x);

           }

           GetTop(OPND,&c);

           freestack(&OPTR);

           freestack(&OPND);

           returnc;

}

5.  Main函数实现

Main函数实现

void main(){

    intc;

    printf("Pleaseinput one expression:");

   c=EvaluateExpression();

    printf("Result=%d\n",c);

}

  

 6.  源码

可以直接在VS上进行编译运行。

#include"stdio.h"

#include"stdlib.h"

#include"ctype.h"

 

typedefint  Status;

#defineSTACK_INIT_SIZE  100

#defineSTACKINCREMENT   10

typedefcharSElemType;      /*放入堆栈的元素的类型*/

 

typedefstruct{

    SElemType*base;

    SElemType*top;

    int      stacksize;

}SqStack;

 

//构造一个空栈

Status InitStack(SqStack *S){

    S->base= (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));

    if(!S->base)

                     exit(-1);

           S->top=S->base;

    S->stacksize=STACK_INIT_SIZE;

    return1;

}

void freestack(SqStack *S){

           free(S->base);

 

}

 

//判断是否为空栈

Status StackEmpty(SqStackS){

    if(S.top== S.base)

        return1;

    else

        return0;

}

 

//e返回S的顶元素

Status GetTop(SqStackS, SElemType *e){

    if(S.top== S.base)

        return-1;

    *e =*(S.top-1);

    return1;

}

//插入e为新的顶元素

Status Push(SqStack *S, SElemTypee){

    if((S->top- S->base) >= S->stacksize){

        S->base= (

                   SElemType*)realloc(S->base,

                  (S->stacksize+STACKINCREMENT)*sizeof(SElemType)

                  );

        if(!S->base)

           exit(-1);

        S->top= S->base +S->stacksize;

        S->stacksize+= STACKINCREMENT;

    }

    *(S->top)=e;

    S->top++;

    return1;

}

//删除S的顶元素,并用e返回其值

Status Pop(SqStack *S, SElemType *e){

    if(S->top== S->base)

        return-1;

    S->top--;

    *e =*(S->top);

    return1;

}

//从栈底到栈顶依次对S的每个元素调用函数Visit(),一旦失败操作无效

Status ListTraverse(SqStackS,Status(*visit)(SElemType)){

    SElemType*p;

    p=S.base;

    for(p=S.base;p<S.top;p++)

        (*visit)(*p);

 

    return1;

}

//输出元素e

Status output(SElemTypee){

    printf("%d",e);

    return 1;

}

 

 

/*计算整数表达式的值

 *表达式必须以#结束

 *表达式中可以出现多位数字,

 *表达式中可以出现空格

 *运算符包括+,-,*,/,(,)

 *运算结果可以是多位整数,并以整数的形式返回

 */

 

 

 

/*判断输入的某个字符是否是运算符

 *c表示输入的字符

 *op数组中存放系统能识别的运算符

 */

Status in(charc,charop[]){

    char*p;

    p=op;

    while(*p!= '\0'){

        if(c== *p)

            return1;

        p++;

    }

    return0;

}

/*比较两个运算符的优先级

 *ab中存放待比较的运算符

 *'>'表示a>b

 *'0'表示不可能出现的比较

 */

char Precede(chara, charb){

    inti,j;

    charpre[][7]={        

           /*运算符之间的优先级制作成一张表格*/

        {'>','>','<','<','<','>','>'},

        {'>','>','<','<','<','>','>'},

        {'>','>','>','>','<','>','>'},

        {'>','>','>','>','<','>','>'},

        {'<','<','<','<','<','=','0'},

        {'>','>','>','>','0','>','>'},

        {'<','<','<','<','<','0','='}};

    switch(a){

        case'+':i=0; break;

        case'-':i=1; break;

        case'*':i=2; break;

        case'/':i=3; break;

        case'(':i=4; break;

        case')':i=5; break;

        case'#':i=6; break;

    }

    switch(b){

        case'+':j=0; break;

        case'-':j=1; break;

        case'*':j=2; break;

        case'/':j=3; break;

        case'(':j=4; break;

        case')':j=5; break;

        case'#':j=6; break;

    }

    returnpre[i][j];

}

/*进行实际的运算

 *ab中分别以整数的形式存放两个待运算的操作数

 *theta中存放代表操作符的字符

 *结果以整数的形式返回

 */

int Operate(inta, chartheta, intb){

    inti,j,result;

    i=a;

    j=b;

 

    switch(theta)   {

        case'+':result = i + j; break;

        case'-':result = i - j; break;

        case'*':result = i * j; break;

        case'/':result = i / j; break;

    }

    returnresult;

}

 

/*从输入缓冲区中获得下一个整数或运算符,并通过n带回到主调函数

 *返回值为1表示获得的是运算符

 *返回值为0表示获得的是整形操作数

 */

int getNext(char *n){

    charc;

    *n=0;

    while((c=getchar())=='');  /*跳过一个或多个空格*/

    if(!isdigit(c)){            /*通过函数判断如果字符不是数字,那么只能是运算符*/

        *n=c;

        return1;

    }

    do{                         /*能执行到该条语句,说明字符是数字,此处用循环获得连续的数字*/

        *n=*n*10+(c-'0');       /*把连续的数字字符转换成相对应的整数*/

       c=getchar();

    }    while(isdigit(c));         /*如果下一个字符是数字,进入下一轮循环*/

    ungetc(c,stdin);            /*新读入的字符不是数字,可能是运算符,为了不影响下次读入,把该字符放回到输入缓冲区*/

    return0;

}

 

int EvaluateExpression(){

 

 

           intflag;

           charc;

           charx,theta;

           chara,b;

 

           charOP[]="+-*/()#";

           SqStack  OPTR;

           SqStack  OPND;

 

           InitStack(&OPTR);     

           Push(&OPTR,'#');

           InitStack(&OPND);

           flag=getNext(&c);

 

           GetTop(OPTR,&x);

           while(c!='#'|| x != '#')

           {

                     if(flag== 0)

                     {

                                Push(&OPND,c);

                                flag= getNext(&c);

                     }       

                     else

                     {

                                GetTop(OPTR,&x);

                                switch(Precede(x,c))

                                {

                                case'<'://栈顶元素优先级低                   

                                          Push(&OPTR,c);

                                          flag= getNext(&c);

                                          break;

                                case'='://脱括号并接受下一字符

                                          Pop(&OPTR,&x);

                                          flag= getNext(&c);

                                          break;

                                case'>'://退栈并将运算结果入栈                                       

                                          Pop(&OPTR,&theta);

                                          Pop(&OPND,&b);

                                          Pop(&OPND,&a);

                                          Push(&OPND,Operate(a, theta, b));

                                          break;

                                }

                     }

                     GetTop(OPTR,&x);

           }

           GetTop(OPND,&c);

           freestack(&OPTR);

           freestack(&OPND);

           returnc;

}

 

void main(){

    intc;

    printf("Pleaseinput one expression:");

   c=EvaluateExpression();

    printf("Result=%d\n",c);

}

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值