【笔记】表达式运算 栈练习

tyvj1042 表达式计算

其实这种题,中缀转后缀才蛋疼……

先说如何计算后缀表达式:

从前往后扫表达式;
若遇到数字,则扔进数字栈中。
若遇到算符,则弹出栈顶的两个数字进行计算,再扔进去。
最后答案是数字栈里剩下的一个数。

那么如何中缀转后缀呢?

从前往后扫表达式;
若遇到数字,则直接添加进后缀表达式中。
若遇到算符,则与栈顶比较(若栈为空则扔进栈中):
{
    若当前算符比栈顶算符优先级高,则直接扔进栈里;
    若低,则一直弹出栈顶元素并且添加进后缀表达式中,直到栈为空或者栈顶元素优先级比当前元素低。
    若为左括号,则直接扔入栈中。
    若为右括号,则一直弹出栈顶元素到后缀表达式中,直到栈顶元素为左括号,弹出左括号。
}
扫完后,把栈中元素弹出进入后缀表达式中。

我觉得这个文章讲的不错,比我说的好多了:戳我

还有就是处理负数,只要在负号前面加一个0即可(并不是平常计算用的减号)

据说有一个表达式树的东西,能把前中后缀表达式转换为表达式树的前中后序遍历,然后递归计算即可……这个大神告诉我的@loi_xczhw Orz

不过我做tyvj1043的时候,不知道是OJ出毛病还是我程序有问题,手测无误交上就WA或者RE,所以代码我就贴1042的吧…少个负数和括号的处理而已QAQ

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
#include<cmath>
using namespace std;
typedef long long LL;
LL calc(LL a,LL b,char c)
{
    if(c=='+') return a+b;
    if(c=='-') return a-b;
    if(c=='*') return a*b;
    if(c=='/') return a/b;
    if(c=='^') return (LL)pow(a,b);
}

stack<LL> num;

LL pri[233];

LL solve(string s)
{
    for(int i=0;i<s.length();i++)
    {
        if(s[i]>='0'&&s[i]<='9') 
        {
            int x;
            sscanf(s.c_str()+i,"%d",&x);
            num.push(x);
            for(;i+1<s.length()&&s[i+1]>='0'&&s[i+1]<='9';i++); i++;
        }
        else
        {
            int y=num.top(); num.pop();
            int x=num.top(); num.pop();
            num.push(calc(x,y,s[i]));       
        }
    }
    return num.top();
}

string change(string s)
{
    string str;
    stack<char> oper;
    for(int i=0;i<s.length();i++)
    {
        if(s[i]>='0'&&s[i]<='9') 
        {
            str+=s[i];
            for(;i+1<s.length()&&s[i+1]>='0'&&s[i+1]<='9';i++) str+=s[i+1];
            str+=" ";
        }
        else
        {
            if(oper.empty()) oper.push(s[i]);
            else
            {
                if(pri[s[i]]>pri[oper.top()])
                {
                    oper.push(s[i]);
                }
                else 
                {
                    while(oper.size()&&pri[s[i]]<=pri[oper.top()])
                    {
                        char x=oper.top(); oper.pop();
                        str+=x;
                    }
                    oper.push(s[i]);
                }
            }
        }
    }
    while(oper.size())
    {
        char x=oper.top();
        str+=x;
        oper.pop();
    }
    return str;
}


int main()
{
    pri['+']=pri['-']=1;
    pri['*']=pri['/']=2;
    pri['^']=3;
    string s;
    cin>>s;
    string str=change(s);
    cout<<str<<endl;
    printf("%d",solve(str));
    return 0;
}
/*
2^3+1

9+2*3+10/2

100-1-1-1-1-1-2^4

5-1-1-1-1-1-2^4

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值