本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我会认真改正的。同时也希望文章能够让你有所收获,与君共勉!

表达式求值

给定一个表达式,其中运算符仅包含+,-,*,/(加 减 乘 整除),可能包含括号,请你求出表达式的最终值。

注意:

数据保证给定的表达式合法。

题目保证符号 - 只作为减号出现,不会作为负号出现,例如,-1+2,(2+2)*(-(1+1)+2) 之类表达式均不会出现。

题目保证表达式中所有数字均为正整数。

题目保证表达式在中间计算过程以及结果中,均不超过 231−1。

题目中的整除是指向 0 取整,也就是说对于大于 0 的结果向下取整,例如 5/3=1,对于小于 0 的结果向上取整,例如 5/(1−4)=−1

C++和Java中的整除默认是向零取整;Python中的整除//默认向下取整,因此Python的eval()函数中的整除也是向下取整,在本题中不能直接使用。

输入格式

共一行,为给定表达式。

输出格式

共一行,为表达式的结果。

数据范围

表达式的长度不超过 105。

输入样例:

(2+2)*(1+1)

输出样例:

8

算法原理

①从表达式中分离出一个个数字整体(所以while循环对于“123”这样的整个数作为整体处理。)

②遇到符号,要按照符号的优先级运算。

这里的op是优先级单调递增栈。

  • 如果当前运算优先级比栈顶高,就直接压栈。
  • 如果当前的与之前相等或更低,且符号栈的顶部符号不是左括号(,且符号栈存在符号,则先进行取栈顶符号运算,再将当前符号加入到符号栈中-。如:2+3*4+5,符号栈先进+,*号比+的优先级要大,所以直接进栈,后面的加号比*的优先级要小,所以要先进行乘法运算

③括号是特殊处理的,如果没有遇到右括号,则运算最多只能处理到上一个左括号,例如2*(3+4),在加号位置不能先算2*3,而是先等待,因为符号栈顶部是(,再括号里面如果存在像2*(2+3*4+5),按照规则2也会先把3*4算出来并放进数字栈中,直到遇到)就从右到左取出数字栈中的数字(符号栈顶的符号)进行运算直至左括号(。

代码实现

#include <iostream>
#include <string>
#include <algorithm>
#include <stack>
#include<unordered_map> using namespace std; stack<int> num;
stack<char> op; void eval(){
int b = num.top(); num.pop();
int a = num.top(); num.pop();
char c =op.top() ;op.pop();
int x ;
if(c == '+') x = a+b;
else if(c == '-') x= a-b;
else if(c == '*') x= a*b;
else x = a/b;
num.push(x);
} int main(void){
unordered_map<char,int> pr{{'+',1},{'-',1},{'*',2},{'/',2}}; // 定义恏优先级
string str; cin >> str; for(int i=0; i < str.size() ; i++){
auto c = str[i];
if(isdigit(c)){
int x = 0, j=i;
while(j<str.size() && isdigit(str[j])){ // 将字符串转化成数字
x = x * 10 + str[j++] - '0';
// j++;
}
i = j-1;
num.push(x);
}
else if (c == '('){ // 左括号直接进符号栈
op.push(c);
}
else if (c == ')'){ // 右括号:从右到左进行运算,知道遇到左括号停下,并且弹出左括号
while(op.top() != '(') eval();
op.pop();
}
else{ // 遇到普通操作符
// 符号栈不为空,栈顶符号不为"(",当前符号的优先级比栈顶的要小(-,+),说明栈顶符号为*/,
while(op.size() && op.top() != '(' && pr[op.top()] >= pr[c]) eval();
op.push(c); // 要先进行乘除运算后再将+,-存入符号栈中。
}
} while(op.size()) eval(); // 最后对+,-运算进行操作
cout << num.top() << endl; // 最后的num一定是运算结果。
return 0;
}

最新文章

  1. T-SQL:毕业生出门需知系列(九)
  2. 关于 ASP.NET MVC 中的视图生成
  3. js调用php和php调用js的方法举例
  4. Linux CentOS6.5下安装Oracle ASM
  5. 项目规范性检测工具Lint
  6. Cache的使用
  7. How do I create an installation log?
  8. java转换流
  9. dbda封装类(包括:返回二维数组、Ajax调用返回字符串、Ajax调用返回JSON)
  10. 2-06. 数列求和(20)(ZJUPAT 数学)
  11. CentOS-6.6下Tomcat-7.0安装与配置(Linux)
  12. MYSQL PGA SGA设置
  13. 初探CSRF在ASP.NET Core中的处理方式
  14. WebService短信网关配置
  15. Java中的“&amp;”和“&amp;&amp;”的区别
  16. ZOJ 3949 Edge to the Root( 树形dp)
  17. Shadow DOM及自定义标签
  18. [leetcode]254. Factor Combinations因式组合
  19. alter日志报WARNING: too many parse errors
  20. ASP.NET MVC:4 Ways To Prevent Duplicate Form Submission(转载)

热门文章

  1. 第七十一篇:Vue组件的私有和全局注册
  2. CSS基础第一篇:图片插入&lt;img&gt;,文本空格
  3. 01_Linux基础-部署-VMware-Xshell-Xftp-内核-安迪比尔定理
  4. KingbaseES R6 通过脚本构建集群案例
  5. 国产PLM软件在创新实践中强势崛起
  6. linux下搭建ftp文件服务器
  7. Java中的SPI原理浅谈
  8. python基础__十大经典排序算法
  9. 11. 第十篇 网络组件flanneld安装及使用
  10. redis cluster 6.2集群