NYOJ 35 表达式求值

题目:http://acm.nyist.net/JudgeOnline/problem.php?pid=35

本题是求算数表达式的值。操作数是大于等于的实数,操作符有 + ,- ,*,/,()

只要开两个栈,一个记录操作符,一个记录后缀表达式。

即:把原始的中缀表达式转换成后缀表达式(逆波兰式),然后进行计算。

前缀和后缀表示法有三项公共特征:
操作数的顺序与等价的中缀表达式中操作数的顺序一致
不需要括号
操作符的优先级不相关
中缀转化为后缀算法:

a. 得到一操作符或操作数;
b. 若输入为操作数,则输出到数组,转a;
c. 若输入为‘(’,压栈,转a;
d. 若输入为‘)’,栈顶出栈,输出到数组,直至栈顶为‘(’,不输出到数组(抛弃),转a;
e. 若输入为操作符,
若栈空或栈顶为‘(’或操作符.忧先级大于栈顶操作符,压栈,转a
若操作符优先级小于栈顶操作符,则出栈,输出至数组,转e;
d. 若输入结束,出栈,输出到数组,直至栈空。


具体转换方法,参考:http://blueve.me/archives/318

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <string>
using namespace std;

int priority[100];

//初始化操作符优先级
void initPri()
{
    priority['('] = 1;
    priority['+'] = 2;
    priority['-'] = 2;
    priority['*'] = 3;
    priority['/'] = 3;
}

//a是符号栈顶,b是当前判断符号
//a>=b,返回true;a<b,返回false
bool judgeOpePri(char a,char b)
{
    return priority[a] >= priority[b] ? true : false;
}
//两个参数:中缀表达式,生成的后缀表达式
void convert(string infixExp,stack<string> &postfixExp)
{
    //运算符栈
    stack<char> opS;
    //临时操作数
    string digitTemp;
    //临时操作符
    string operTemp;
    int len = infixExp.length();
    bool hasDigit = false;
    //过滤掉'='
    for(int i=0; i<len-1;)
    {
        //如果是操作数的一部分
        while((isdigit(infixExp[i]) || infixExp[i] == '.') && i<len-1)
        {
            hasDigit = true;
            digitTemp.push_back(infixExp[i]);
            i++;
        }
        if(hasDigit == true)
        {
            postfixExp.push(digitTemp);
            digitTemp = "";
            hasDigit = false;
        }
        else
        {
            //如果操作符栈是空的,就入栈
            if(opS.empty())
            {
                opS.push(infixExp[i]);
                i++;
            }
            //注意对于'('同等优先级是不起作用的
            else if(infixExp[i] == '(')
            {
                opS.push(infixExp[i]);
                i++;
            }
            //弹出"()"之内的所有运算符
            else if(infixExp[i] == ')')
            {
                while(!opS.empty())
                {
                    char c = opS.top();
                    operTemp = "";
                    operTemp.push_back(c);
                    opS.pop();
                    if(c == '(')
                    {
                        break;
                    }
                    else
                    {
                        postfixExp.push(operTemp);
                    }
                }
                i++;
            }
            //操作符栈顶的优先级大
            else if(judgeOpePri(opS.top(),infixExp[i]) == true)
            {
                char c = opS.top();
                operTemp = "";
                operTemp.push_back(c);
                opS.pop();
                postfixExp.push(operTemp);
                //注意此时不要i++,因为还要继续比较
            }
            //操作符栈顶的优先级小
            else
            {
                opS.push(infixExp[i]);
                i++;
            }
        }
    }
    //清空符号栈
    while(!opS.empty())
    {
        char c = opS.top();
        operTemp = "";
        operTemp.push_back(c);
        opS.pop();
        postfixExp.push(operTemp);
    }
}

double answerQ(stack<string> &postfixExp)
{
    stack<string> couterFix;
    stack<double> resultSta;
    while(!postfixExp.empty())
    {
        couterFix.push(postfixExp.top());
        postfixExp.pop();
    }
    double a,b;
    while(!couterFix.empty())
    {
        string c = couterFix.top();
        double d;
        couterFix.pop();
        int cas = 5;
        if(strcmp(c.c_str(),"+") == 0) cas = 0;
        else if(strcmp(c.c_str(),"-") == 0) cas = 1;
        else if(strcmp(c.c_str(),"*") == 0) cas = 2;
        else if(strcmp(c.c_str(),"/") == 0) cas = 3;
        if(cas!=5)
        {
            double a = resultSta.top();
            resultSta.pop();
            double b = resultSta.top();
            resultSta.pop();
            switch(cas)
            {
            case 0:
            {
                resultSta.push(b + a);
                break;
            }
            case 1:
            {
                resultSta.push(b - a);
                break;
            }
            case 2:
            {
                resultSta.push(b * a);
                break;
            }
            case 3:
            {
                resultSta.push(b / a);
                break;
            }
            default:
            {}
            }
        }
        else
        {
            sscanf(c.c_str(),"%lf",&d);
            resultSta.push(d);
        }
    }
    return resultSta.top();
}
int main()
{
/*#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif*/
    int n;
    scanf(" %d",&n);
    initPri();
    while(n--)
    {
        string infixExp;
        stack<string> postfixExp;
        cin>>infixExp;
        convert(infixExp,postfixExp);
        double ans = answerQ(postfixExp);
        printf("%.2lf\n",ans);
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值