计算字符串表达式的值

步骤:1、将表达式转化成逆波兰式         2、求逆波兰式的值

一、将表达式转化成逆波兰式

举个简单的例子,平常我们写的数学表达式a+b,就是一种中缀表达式,写成后缀表达式就是ab+。再举一个复杂的例子,中缀表达式(a+b)*c-(a+b)/e的逆波兰式是ab+c*ab+e/-。

(1)首先,需要分配1个栈,用于临时存储运算符,此运算符在栈内遵循越往栈顶优先级越高的原则;

 

(2)从中缀式的左端开始逐个读取字符x,逐序进行如下步骤:

1.若x是操作数,,将x直接加入ans后边;

2.若x是运算符,则分情况讨论:

   若x是'(',则直接压入栈s;

 若x是')',则将距离栈s栈顶的最近的'('之间的运算符,逐个出栈,依次加入ans,此时抛弃'(';

 若x是除'('和')'外的运算符,则再分如下情况讨论:

   若当前栈s的栈顶元素为'(',则将x直接压入栈s;

   若当前栈s的栈顶元素不为'(',则将x与栈s的栈顶元素比较,若x的优先级大于栈顶运算符优先级,则将x直接压入栈s。否者,将栈顶运算符弹出,加入ans,直到栈顶运算符优先级别低于(不包括等于)x的优先级,此时再则将x压入栈;

 【第二步是一个循环,要把中缀式读完。第三步是在循环之外】

 

(3)在进行完(2)后,检查栈是否为空,若不为空,则将栈中元素依次弹出并加入ans

(4)完成上述步骤后,ans便为逆波兰式输出结果。 

#include<bits/stdc++.h>
using namespace std;
int judge(char data){
    int res = 0;
    switch (data) {
        case '+':
            res = 1;
            break;
        case '-':
            res = 1;
            break;
        case '*':
            res = 2;
            break;
        case '/':
            res = 2;
            break;
        default:
            break;
    }
    return res;
}
string getNiBolan(string str){
    string newStr = "";
    stack<int> s;
    int length =(int)str.length();
    for (int i =0 ; i<length; i++) {
        char cur = str[i];
        if (cur == '(') {
            //新元素为(直接压栈
            s.push(cur);
        }
        else if(cur ==')')
        {
            //新元素为)打印出(上面所有的
            if(!s.empty())
            {
                //栈中有元素
                while (!s.empty()) 
                {
                    char peep = s.top();
                    s.pop();
                    if (peep != '(') {
                        newStr += peep;
                    }
                    else 
                        break;
                }
            }
            else
            {
                //没有元素遇到(直接报错
                cout<<"the input is error";
                exit(1);
            }
        }
        else if ( ('A'<=cur&&cur<='Z')||('a'<=cur && cur<='z')||('0'<=cur && cur<='9') )
        {
            //新元素为字符或者数字直接赋值
            newStr += cur;
        }
        else{
            //新元素为+-*/
            int curJudge1 = judge(cur);
            //当栈不为空的时候判断
            if (!s.empty()) 
            {
                while (!s.empty()) 
                {
                    char peep = s.top();
                    //栈顶不为(
                    int curJudge2 = judge(peep);
                        //新元素大于等于栈顶的等级,直接压栈
                    if (curJudge1 >= curJudge2) 
                    {
                        s.push(cur);
                        break;
                    }
                    else
                    {
                            //小于就赋值
                        s.pop();
                        newStr += peep;
                    }
                }
                if(s.empty())
                    s.push(cur);
            }
            else
            {
                //问题2;忘记在空的时候直接压栈
                s.push(cur);
            }
        }
    }
    //问题1 忘记了输出出栈中的所有元素
    while (!s.empty()) {
        newStr += s.top();
        s.pop();
    }
    return newStr;
}
int main()
{
    string s = "(a+b)*c-(a+b)/e";
    s = getNiBolan(s);
    cout<<s;
    return 0;
    
}

2、求逆波兰式的值

Example 1:

Input: ["2", "1", "+", "3", "*"]
Output: 9
Explanation: ((2 + 1) * 3) = 9

Example 2:

Input: ["4", "13", "5", "/", "+"]
Output: 6
Explanation: (4 + (13 / 5)) = 6

分析:弄一个栈,一个一个读逆波兰式,如果是数字就入栈,如果是算符就pop两个出来计算,再把结果压栈

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> s;
        for(auto a : tokens)
        {
            if(a.size()==1 && !isdigit(a[0]))
            {
                int num2 = s.top();
                s.pop();
                int num1 = s.top();
                s.pop();
                switch(a[0])
                {
                    case '+':
                        s.push(num1+num2);break;
                    case '-':
                        s.push(num1-num2);break;
                    case '*':
                        s.push(num1*num2);break;
                    case '/':
                        s.push(num1/num2);break;
                }
                
            }
            else
            {
                s.push(atoi(a.c_str()));//c_str()函数返回一个指向正规C字符串的指针, 内容与本string串相同,atoi用于把字符串数字转为数字
            }
        }
        return s.top();
           
        
    }
};

为了方便程序,我们一般在中缀式转逆波兰式的时候,用一个列表装下每一个token(数字要拼接好) 。

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值