栈的应用—逆波兰表达式

       逆波兰表达式又称为“后缀表达式”。例:4.99*1.06+5.99+6.99*1.06 的后缀表达式为 4.99 1.06 *5.99 +6.99 1.06 +正常写的表达式又称为中缀表达式,如何将一个中缀表达式表达式转换成后缀表达式?这里就要用到栈。但见到一个数时就把他推入栈中,在遇到一个运算符时就将该运算符作用于该栈弹出的两个数(符号)上,将说得结果推入栈中。

举个例子:6 5 2 3 + 8 * +3 * 
①前四个字符放入栈中为:6 5 2 3;
②读到一个+号,2 3 出栈执行+法,结果5在压入栈中,栈中元素为:6 5 5;
③8进栈,栈中元素为:6 5 5 8,读入*,5 8出栈执行运算,结果返回栈,栈中元素:6 5 40
④以此类推,最后栈中元素为288,结果也就为288。

现在要求实现:计算带有括号()的表达式的值,例如:32+76+(29+52*(76-24)-14)/12

思路:
1、使用两个栈,一个数据栈,一个操作符栈。当读到一个操作数时,立即将他放入数据栈中,将操作符放入操作符栈中;
2、如果遇到一个左括号,直接压入操作符栈中;
3、如果遇到右括号弹出操作符栈中的操作符直到弹出左括号为止;
4、如果压入的操作符的优先级较高,那么弹出栈中栈顶元素优先级比他高的,知道遇到比他低的为止;
5、最后若字符栈为空,则结束。

代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//设置运算符的优先级
int level(char op)
{
    int x;
    switch(op)
    {
        case '@': x=-1;break;
        case '(': x=0;break;
        case '+': 
        case '-': x=1;break;
        case '*': 
        case '/': x=2;break;
    }
    return x;
}
//计算值
int cal(int x, int y, char op)
{
    int result;
    switch(op)
    {
        case '+': result=x+y;break;
        case '-': result=x-y;break;
        case '*': result=x*y;break;
        case '/': result=x/y;break;
    }
    return result;
}

//计算表达式
int compute(char s[])
{
    int y,v1,v2,i;
    char ops[100];    //定义运算符栈
    int  vas[100];    //定义数字栈
    int otop,vtop;    //定义栈顶指针
    otop=vtop=-1;
    y=0;
    ops[++top]='@';
    //遍历整个字符串
    while(s[i])
    {
        if(s[i]=='(')                   //如果是左括号直接进栈
            ops[++top]='(';
        else
        {
            if(s[i]>'0'&& s[i]<'9')
            {   //如果是数字转换成int型
                while(s[i]>'0'&& s[i]<'9')
                {
                    y=y*10+(s[i++]-48);
                }
                vas[++top]=y;
                i--;
            }
        }
        else
        {
             if(s[i]=='+'||s[i]=='-'||s[i]=='*' ||s[i]=='/' )
             {
            //如果栈顶运算符的优先级大于s[i]的优先级,出栈进行计算操作
                while(level[s[i]]<level[ops[otop]])
                {
                    op=ops[otop--];  //运算符出栈
                    v1=vas[vtop--];
                    v2=vas[vtop--];  //数据出栈
                    vas[++top]=cal(v1,v2,op); //计算后的数据在进栈
                }
                //否则直接进栈
                ops[++top]=s[i];
              }
        }
        else //如果是右括号
        {
            if(s[i]==')')
            {
                //将左括号内的运算符都出栈
                while(ops[otop]!='(')
                {
                    op=ops[otop--];  //运算符出栈
                    v1=vas[vtop--];
                    v2=vas[vtop--];  //数据出栈
                    vas[++top]=cal(v1,v2,op); //计算后的数据在进栈
                }
                otop--;       //左括号出栈
            }
        }
        i++;
    }
    //字符串遍历完,栈中可能还有运算符
    while(otop!=0)
    {
        op=ops[otop--];  //运算符出栈
        v1=vas[vtop--];
        v2=vas[vtop--];  //数据出栈
        vas[++top]=cal(v1,v2,op); //计算后的数据在进栈
    }
    return vas[vtop];
}

//主函数
int main()
{
    char s[100];
    int value;
    gets(s);
    value=compute(s);
    printf("%s=%d",s,value); 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值