表达式求值

思路:通过逆波兰表达式求值的方法进行求解,可以有效的解救括号问题,因为后缀式不需要用括号来确定优先级。

解救方案:

1、中缀式转为后缀式

(1)

(2) 算法实现

(a) 定义一个空栈s,和一个string数组suffix

(b)对中缀表达式每个字符进行逐个接收。

(c)如果得到的是数字或者小数点,直接按顺序存到suffix内

(d)如果得到的是‘(’,压入栈中。

(e)如果得到的是‘)’,栈顶出栈存到suffix内,直至栈顶元素为‘)’,然后栈顶出栈,这一步可以解决小括号的问题。

 (f)如果得到的是运算符,则将此与栈顶元素进行比较,如果优先级小于栈顶元素,则将栈顶元素存到suffix中,并且出栈,然后继续将栈顶元素与该运算符比较,直至该运算符大于栈顶元素,则将其入栈。

(g)遍历结束后,将栈内元素出栈,存到suffix内。至此,suffix就是按照后缀式的顺序存储的了。

2、后缀式运算

(1)依照从左到右的顺序读取suffix,如果得到的是操作数或者‘.’,则将其读取完整后处理为数字格式入栈,如果是运算符,则进行计算,计算该运算符栈顶的两个元素,将该两个栈顶元素依次出栈,新得的结果入栈。

(2)读取结束后,栈底等于栈顶且为最后运算结果,则运算正确。

code:

#include<iostream>
#include<cstdio>
#include<string>
#include<stack>
using namespace std;
int weight(char a) // 运算符权重
{
    if(a == '+' || a == '-')
        return 1;
    else if(a == '*' || a == '/')
        return 2;
    else
        return 0;
}
int midtosuffix(string &mids,string &suffixs) //中缀式转后缀式
{
    stack<char > s; //用来处理括号问题
    s.push('#');

    int i = 0;
    while(i < mids.length()-1)
    {
        if(mids[i] == '(')
        {
            s.push(mids[i]);
            i++;
        }
        else if(mids[i] == ')')
        {
            while(s.top() != '(')
            {
                suffixs += s.top();
                suffixs += ' ';
                s.pop();
            }
            s.pop();
            i++;
        }
        else if(mids[i] == '+' || mids[i] == '-' || mids[i] == '*' || mids[i] == '/')
        {
            while(weight(s.top()) >= weight(mids[i]))
            {
                suffixs += s.top();
                suffixs += ' ';
                s.pop();
            }
            s.push(mids[i]);
            i++;
        }
        else
        {
            while(mids[i] >= '0' && mids[i] <= '9' || mids[i] == '.')
            {
               suffixs += mids[i++];
            }
            suffixs += ' ';
        }
    }

    while(s.top() != '#')
    {
        suffixs += s.top();
        suffixs += ' ';
        s.pop();
    }
}
double cal(string suffixs)//后缀表达式的运算
{
    stack<double> s;
    int i = 0;
    double x,y;
    while(i < suffixs.length())
    {
        if(suffixs[i] == ' ')
        {
            i++;
            continue;
        }
        if(suffixs[i] == '+')
        {
            x = s.top();
            s.pop();
            x += s.top();
            s.pop();
            i++;
        }
        else if(suffixs[i] == '-')
        {
            x = s.top();
            s.pop();
            x = s.top() - x;
            s.pop();
            i++;
        }
        else if(suffixs[i] == '*')
        {
            x = s.top();
            s.pop();
            x *= s.top();
            s.pop();
            i++;
        }
        else if(suffixs[i] == '/')
        {
            x = s.top();
            s.pop();
            x = s.top()/x;
            s.pop();
            i++;
        }
        else
        {
            x = 0;
            while(suffixs[i] >= '0' && suffixs[i] <= '9')
            {
                x *= 10;
                x += suffixs[i]-'0';
                i++;
            }
            if(suffixs[i] == '.')
            {
                y = 0;
                double k = 10.00;
                i++;
                while(suffixs[i] >= '0' && suffixs[i] <= '9')
                {
                    y += (suffixs[i]-'0')/k;
                    k *= 10.00;
                    i++;
                }
                 x += y;
            }
        }
        s.push(x);
    }
    return s.top();//返回运算结果
}
int main()
{
    int n;
    scanf("%d",&n);
    string mids,suffixs;
    while(n--)
    {
        cin>>mids;
        suffixs = "";
        midtosuffix(mids,suffixs);
        cout<<suffixs<<" ="<<endl;
        //printf("%.2f\n",cal(suffixs));
    }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值