逆波兰表达式(后缀表达式) 写 表达式求值

表达式求值,可以用栈,这里有栈的一些表达和使用、包括表达式求值
这里是伪代码以及AC代码可以去HDOJ测评
现在我用后缀表达式来重做一次。可以计算简单的加减乘除带括号。

#include<stdio.h>
#include<stdlib.h>
/*
 * 1建立两个栈:符栈、逆波兰表达式栈(存放数字和运算符)
 * 2char ch;
 * 3while(ch!='\n')
 *      if(ch==' ') continue;scanf("%c",&ch)
 *      if(isNum(ch)) 逆栈.push(ch);scanf("%c",&ch)
 *      else
 *          if(Empty(符栈)) 符栈.Push(ch);scanf("%c",&ch)
 *          else Top(符栈,e);
 *               if(precede(e,ch)=='<') 符栈.Push(ch);scanf("%c",&ch)    //符栈顶的优先级低
 *               else if(precede(e,ch)=='>') Pop(符栈,e);逆栈.Push(e);//ch不变,继续和符栈顶比较
 *               else Pop(符栈,e);scanf("%c",&ch)
 * while(!Empty(符栈)) Pop(符栈,e);逆栈.Push(e);
 * 至此,逆波兰表达式建立
 *
 * 接下来,通过逆波兰表达式计算结果
 *
 * 数据结构采用顺序栈,栈的数据是char类型
 * 所以会出现一些限制:
 * 因为栈存储的数据是char,所以表达式中的数字不能是双数,且不能出现小数包括由于除法导致的小数,以及不能是负数
 * 仅限于十以内整数加减乘除以及括号
 */
#define STACK_INIT_SIZE 25  //栈空间最大/表达式最长
#define Status char
#define SElemType char
typedef struct{
    SElemType * base;
    SElemType * top;
    int stacksize;  //栈当前已分配的空间
}SqStack;

//S.top指向栈顶元素的下一个

Status InitStack(SqStack &S){
    S.base = (SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
    S.top = S.base;
    S.stacksize = STACK_INIT_SIZE;
    return 1;
}
char precede(char a, char b){ //运算符的优先关系
    char mark[6][6] = { {'>','>','<','<','<','>'},
                        {'>','>','<','<','<','>'},
                        {'>','>','>','>','<','>'},
                        {'>','>','>','>','<','>'},
                        {'<','<','<','<','<','='},
                        {'>','>','>','>',' ','>'}
    };
    char ch[6]={'+','-','*','/','(',')'};
    for(int i=0;i<6;i++){
        if(a==ch[i])
            for(int j=0;j<6;j++)
                if(b==ch[j]) return mark[i][j];
    }
}
int operate(char x, char o, char y){ //二元运算
    int a = (int)x-48; int b = (int)y-48;
    switch(o){
        case '+': return a+b;
        case '-': return a-b;
        case '*': return a*b;
        case '/': return a/b;
    }
}
Status StackEmpty(SqStack S){
    if(S.top==S.base) return 1;
    return 0;
}
Status Top(SqStack &S, SElemType &e){
    if(S.top==S.base) return 0;
    e = *(S.top-1);
    return 1;
}
Status Push(SqStack &S, SElemType e){
    if(S.top-S.base>=STACK_INIT_SIZE)
        S.base = (SElemType *)realloc( S.base, (STACK_INIT_SIZE+S.stacksize)*sizeof(SElemType));
    *S.top++ = e;
    return 1;
}
Status Pop(SqStack &S, SElemType &e){
    if(S.top==S.base) return 0;
    e = *--S.top;
    return 1;
}
int StackLength(SqStack S){
    int n=0;
    while(S.top--!=S.base) n++;
    return n;
}
void EvaluateExpression(){
    SqStack S,T;    //符栈,逆波兰表达式栈(逆栈)
    InitStack(S);
    InitStack(T);

    //中序表达式输入,转换成后序表达式
    char ch,e;
    scanf("%c",&ch);
    while (ch!='\n'){
        if (ch==' '){scanf("%c",&ch);continue;}
        if ((48<=ch && ch<=57)||97<=ch && ch<=122) {Push(T,ch);scanf("%c",&ch);}
        else
            if(StackEmpty(S)) {Push(S,ch);scanf("%c",&ch);}
            else{
                Top(S,e);
                if(precede(e,ch)=='<') {Push(S,ch);scanf("%c",&ch);}
                else if(precede(e,ch)=='=') {Pop(S,e);scanf("%c",&ch);}
                else {
                    Pop(S,e);
                    Push(T,e);
                }
            }
    }
    while(!StackEmpty(S)){
        Pop(S,e);
        Push(T,e);
    }
    //至此,T为逆波兰表达式
    int i=0;
    while(T.top!=(T.base+i)) printf("%c",*(T.base+i++));//输出逆波兰表达式
    printf("\n");

//    计算逆波兰表达式
//    接下来就是通过利用逆波兰表达式的特点,通过逻辑,计算结果
    SqStack p;
    while (StackLength(T)>=3){
        i=0;
        while (*(T.base+i)>47) i++;
        char sum = (char)(operate(*(T.base+(i-2)), *(T.base+i), *(T.base+i-1))+48);
        *(T.base+i-2)=sum;
        for(int j=i-1;T.top!=(T.base+j+2);j++) *(T.base+j)=*(T.base+j+2);
        T.top = T.top-2;
    }
    printf("%c",*T.base);
}

int main(){
    EvaluateExpression();
    return 1;
}
/*
中序:
 1+2*(4-1)-8/4
后序:
 1241-*+84/-
表达式结果:5

中序:
(2*4)-6/3*(2-1)-1+1*2
 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

正在学C++

2角不嫌多,1角不嫌少

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

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

打赏作者

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

抵扣说明:

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

余额充值