Leetcode--150--逆波兰表达式求值(后缀表达式求值)【C++、栈实现】

150. 逆波兰表达式求值

根据 逆波兰表示法,求表达式的值。
有效的运算符包括 +, -, *, /。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

说明:
整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

示例 1:
输入: [“2”, “1”, “+”, “3”, “*”]
输出: 9
解释: 该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

示例 2:
输入: [“4”, “13”, “5”, “/”, “+”]
输出: 6
解释: 该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6

示例 3:
输入: [“10”, “6”, “9”, “3”, “+”, “-11”, “", “/”, "”, “17”, “+”, “5”, “+”]
输出: 22
解释:
该算式转化为常见的中缀算术表达式为:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22

逆波兰表达式:
逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。
平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。
该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。

逆波兰表达式主要有以下两个优点:
去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。

解法
  1. 从左至右扫描后缀表达式的各项(包括运算数和运算符)
  2. 如果遇到运算数 就直接放入栈中
  3. 如果遇到运算符 则从堆栈中弹出适量的运算数,并让计算的结果入栈
  4. 最后 栈顶的元素就是表达式的结果值
class Solution {
     
public:
    int evalRPN(vector<string>& tokens) {
     //注意这里的vector里面是string 类型,后面要用“ ”而不是' '
          if(tokens.size()==0)
          return 0;
          stack<int>nums;
          int n1,n2;
          for(int i=0;i<tokens.size();++i)
          {
     
              if(tokens[i]=="+")
              {
     
                  n1=nums.top();
                  nums.pop();
                  n2=nums.top();
                  nums.pop();
                  nums.push(n1+n2);
              }
              else if(tokens[i]=="-")
              {
     
                  n1=nums.top();
                  nums.pop();
                  n2=nums.top();
                  nums.pop();
                  nums.push(n2-n1);
              }
              else if(tokens[i]=="*")
              {
     
                  n1=nums.top();
                  nums.pop();
                  n2=nums.top();
                  nums.pop();
                  nums.push(n1*n2);
              }
              else if(tokens[i]=="/")
              {
     
                  n1=nums.top();
                  nums.pop();
                  n2=nums.top();
                  nums.pop();
                  nums.push(n2/n1);
              }
              else
              {
     
                  int n=stoi(tokens[i]);//用到了stoi函数 头文件是cstring
                  nums.push(n);
              }  
          }
          return nums.top();
    }
};
完整C++程序测试

测试 "1 2 5 * +" 式子的值 1+2*5=11
写程序的 时候特别要注意以下两点:

  1. 这里的函数接口是string 不是char因此后面判断运算符 时 要用双引号 " " 而不是 单引号' '
  2. 当读到的元素不是操作符时 说明是操作数 则要把 string 类型转换为 int 类型,然后存入栈中;这里用到的转换方法为使用函数 atoi 因为这里是string类型 还需先将string转为const char*。也可以使用string sstream 方法 使用的时候注意。
函数原型:
const char *c_str();
函数说明:
c_str()函数返回一个指向正规C字符串的指针常量, 内容与本string串相同.这是为了与c语言兼容,在c语言中没有string类型,故必须通过string类对象的成员函数c_str()把string 对象转换成c中的字符串样式。c_str()转换到第一个非数字字符为止。
#include 
#include 
#include 
#include 
#include 


using namespace std;

int evalRPN(vector<string>& tokens) {
     
        int len = tokens.size();
        int value1, value2, ans;
        
        stack<int>value;
        for(int i = 0; i < len; ++i)
        {
     
           if(tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/")
            {
     
                value2 = value.top();
                value.pop();
                value1 = value.top();
                value.pop();
                if(tokens[i] == "+") ans = value1 + value2;
                else if(tokens[i] == "-") ans = value1 - value2;
                else if(tokens[i] == "*") ans = value1 * value2;
                else ans = value1 / value2;
                value.push(ans);
            }
            else
            {
     
                int temp=atoi(tokens[i].c_str());
                value.push(temp);
            }
        }
        return value.top();
}

int main()
{
     
    vector<string> s;
    s.push_back("1");
    s.push_back("2");
    s.push_back("5");
    s.push_back("*");
    s.push_back("+");
    int ans=evalRPN(s);
    cout << ans <<endl;
    return 0;

}


你可能感兴趣的:(编程题练习,堆栈,c++)