逆波兰表达式

1、输入一个字符串,将其格式化的储存在一个数组中,以方便的记录表达式中数和各个符号的出现顺序
约定在数组中记录时,每个数或符号用两个整数来记录
第一个整数记录该位是什么东西,0表示是一个数,1表示是括号,2表示反括号,3、4、5、6分别表示乘除加减号
如果该位是一个数,那么第二个整数记录着个数的具体取值,否则记录该位的符号的ASCII码
比如字符串"(1-23)"会被转化成二位数组 ,  ,  ,  , }
这个转化过程每什么技巧性,对原字符串各位顺次判断并处理即可
原先的字符串中可能出现一元运算符正号'+'和负号'-',为了处理方便,一律在其前面加个0,改写成"0+..."或者"0-..."
另外为了之后转化逆波兰表达式方便,处理过程中会在转化出的数组的首尾一律添加一对括号

2、将之前所提到的格式数组转化为逆波兰表达式
约定依然用二位数组记录一个逆波兰表达式,并且格式与之前的数组相同,除了没有括号以外
比如逆波兰表达式 1 2 - 35 +,会被记录成{  ,  ,  ,  , }
转化时,需要用一个栈
具体转化操作如下:
顺次处理格式数组的每一位,对其作判断
如果该位是一个数或者是括号'(',,将其入栈
如果该位是乘号'*'或者除号'/',不断进行出栈操作直到栈顶元素是个括号'('或者加号'+'或者减号'-',然后将这个乘号或者除号入栈
如果该位是加号'+'或者减号'-',不断进行出栈操作直到栈顶元素是个括号'(',然后将这个加号或者减号入栈
如果该位是反括号')',那么不断进行出栈操作直到有一个括号'('出栈

在上述操作中,所有的出栈元素,除了括号'('以外,都被顺次添加到所要生成的逆波兰表达式的末尾
这样就转化出了一条逆波兰表达式

3、对逆波兰表达式求值
求值时,也需要用到一个栈
求值步骤如下:
顺次处理逆波兰表达式的每一位,对其作判断
如果该位是一个数,将这个数入栈
如果该位是一个运算符,那么连续进行两次出栈操作,可以得到栈顶的两个元素,对这两个元素用该位的运算符做运算,将所得的结果入栈
比如,如果当时栈顶元素是3,次栈顶的元素是2,运算符是减号'-',那么连续两次出栈得到3和2两个元素,再将2-3的运算结果1入栈
注意有些运算符(减号和除号)不符合交换律,因此运算时必须是次栈顶元素在前、栈顶元素在后,顺序不能反

当每一位都处理完了之后,只要输入的是一个合法的逆波兰表达式,必然栈中只剩下一个元素,这个元素就是逆波兰表达式求值的结果

源代码如下:

#include <stdio.h>
#include <ctype.h>

void transform(char *str,int a[][2],int *n)
//将输入的字符串转化为格式化的数组以记录输入的表达式,str为输入的字符串,a为目标数组,n记录数组a的大小 
{
    int i;
    *n=1;
    a[0][0]=1;
    a[0][1]='(';//在表达式首添加一个括号
    for (i=0;str[i];)
    {
        if (isdigit(str[i]))
        {
            a[*n][0]=0;
            a[*n][1]=0;
            while (isdigit(str[i]))
            {
                a[*n][1]=a[*n][1]*10+str[i]-'0';
                i++;
            }
        }
        else
        {
            if (str[i]=='(') a[*n][0]=1;
            else if (str[i]==')') a[*n][0]=2;
            else if (str[i]=='*') a[*n][0]=3;
            else if (str[i]=='/') a[*n][0]=4;
            else if (str[i]=='+' || str[i]=='-')
            {
                if (i==0 || (!isdigit(str[i-1]) && str[i-1]!=')'))
                {
                    a[*n][0]=0;
                    a[*n][1]=0;
                    (*n)++;
                }
                if (str[i]=='+') a[*n][0]=5;
                else a[*n][0]=6;
            }
            a[*n][1]=str[i];
            i++;
        }
        (*n)++;
    }
    a[*n][0]=2;
    a[*n][1]=')';//在表达式尾添加一个反括号
    (*n)++;
}

void poland(int a[][2],int n,int p[][2],int *m)
//将格式化数组转化为逆波兰表达式,a为输入的数组,n为其长度,p为输出逆波兰表达式的目标,m记录逆波兰表达式的长度 
{
    int i;
    int stack[1000];//转化所用的栈
    int depth;//栈的深度
    depth=0;
    *m=0;
    for (i=0;i<n;i++)
    {
        if (a[i][0]==0) stack[depth++]=i;
        else if (a[i][0]==1) stack[depth++]=i;
        else if (a[i][0]==2)
        {
            while (a[stack[depth-1]][0]!=1)
            {
                depth--;
                p[*m][0]=a[stack[depth]][0];
                p[*m][1]=a[stack[depth]][1];
                (*m)++;
            }
            depth--;
        }
        else if (a[i][0]==3 || a[i][0]==4)
        {
            while (a[stack[depth-1]][0]==0 || a[stack[depth-1]][0]==3 || a[stack[depth-1]][0]==4)
            {
                depth--;
                p[*m][0]=a[stack[depth]][0];
                p[*m][1]=a[stack[depth]][1];
                (*m)++;
            }
            stack[depth++]=i;
        }
        else if (a[i][0]==5 || a[i][0]==6)
        {
            while (a[stack[depth-1]][0]!=1)
            {
                depth--;
                p[*m][0]=a[stack[depth]][0];
                p[*m][1]=a[stack[depth]][1];
                (*m)++;
            }
            stack[depth++]=i;
        }
    }
}

void print_poland(int p[][2],int m)
//打印逆波兰表达式,p为逆波兰表达式,m为表达式长度 
{
    int i;
    for (i=0;i<m;i++)
    {
        if (p[i][0]==0) printf("%d",p[i][1]);
        else printf("%c",p[i][1]);
    }
    putchar('\n');
}

double evaluate(int p[][2],int m)
//对逆波兰表达式求值,p为逆波兰表达式,m为表达式长度
{
    double stack[1000];//求值所用的栈
    int depth;//栈的深度
    int i;
    depth=0;
    for (i=0;i<m;i++)
    {
        if (p[i][0]==0) stack[depth++]=p[i][1];
        else
        {
            double a,b;
            b=stack[--depth];
            a=stack[--depth];
            if (p[i][0]==3) stack[depth++]=a*b;
            else if (p[i][0]==4) stack[depth++]=a/b;
            else if (p[i][0]==5) stack[depth++]=a+b;
            else stack[depth++]=a-b;
        }
    }
    return stack[0];
}

int a[1000][2];
int n;
int p[1000][2];
int m;

main()
{
    transform("5*(8-2)+9",a,&n);
    poland(a,n,p,&m);
    print_poland(p,m);
    printf("The result of the expression is %lf\n",evaluate(p,m));
    return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值