AcWing 3302. 表达式求值 C++

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

注意:

  • 数据保证给定的表达式合法。
  • 题目保证符号 - 只作为减号出现,不会作为负号出现,例如,-1+2,(2+2)*(-(1+1)+2) 之类表达式均不会出现。
  • 题目保证表达式中所有数字均为正整数。
  • 题目保证表达式在中间计算过程以及结果中,均不超过 231−1231−1。
  • 题目中的整除是指向 00 取整,也就是说对于大于 00 的结果向下取整,例如 5/3=15/3=1,对于小于 00 的结果向上取整,例如 5/(1−4)=−15/(1−4)=−1。
  • C++和Java中的整除默认是向零取整;Python中的整除//默认向下取整,因此Python的eval()函数中的整除也是向下取整,在本题中不能直接使用。
  • 输入格式

    共一行,为给定表达式。

    输出格式

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

    数据范围

    表达式的长度不超过 105105。

    输入样例
  • (2+2)*(1+1)
  • 输出样例:
  • 8

思路:

        定义数据栈和操作符栈

        核心就是对操作符进行一个优先级的划分,先说说没有括号的情况

先说说结论:

        1)如果栈顶是+,即将入栈的是+,则先计算,再入栈;

        2)如果栈顶是+,即将入栈的是*,直接入栈;

        3)如果栈顶是*,即将入栈的是+,则先计算,再入栈

        4)如果栈顶是*,即将入栈的是*,则先计算,再入栈

没有括号时候        

ex 1+3+5*7+4

        模拟一遍 

        数据栈: 1 3

        操作栈: +

        这个时候遇到了+号 

        所以要先计算再入栈

        于是

        数据栈: 4 

        操作栈: +

        到后面的5时(因为操作栈顶元素是+ 入栈的是*  栈顶元素不如入栈元素的优先级高,所以不计算直接入栈)

         数据栈: 4 5

        操作栈: + *

        到后面+号前

        数据栈: 4 5 7

        操作栈: + *

        到+号时候 吧操作栈里面所有优先级比+号大的都计算完成 再入栈

        数据栈: 39

        操作栈: +

        最后到4 

        数据栈:39 4

        操作栈: +

        此时跳出循环  但是操作栈不为空 说明还有的操作没做完要继续做

如果有括号

        (2*2)+(1+1)

        首先说明一点 我们在m中 没有定义(  号的优先级的  但是后面进行了查询 所以m中会自动添加 {‘(’,0}  优先级默认是0   

        如果是(我们直接加入到操作栈中就好了 , 直到我们碰到了 )时候 ,直接开始计算括号里面的内容  知道操作符遇到了(时候截止。

一些细节的处理代码注释上面有 !!!

  代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
stack<ll> nums;//数字栈 
stack<char> ops;//操作数栈 
unordered_map<char,int> m={{'+', 1}, {'-', 1}, {'*',2}, {'/', 2} };
//定义优先级 
void caculate(){
	ll a=nums.top();
	nums.pop();
	ll b=nums.top();
	nums.pop();
	char op=ops.top();
	ops.pop();
	ll res;
	if (op == '+') res = b + a;
    if (op == '-') res = b - a;
    if (op == '*') res = b * a;
    if (op == '/') res = b / a;
    nums.push(res);
}
int main(){
	 string s;
	 cin>>s;
	for(int i=0;i<s.size();i++){
		if(s[i]>='0'&&s[i]<='9'){
			//这里需要处理1000 这样的数字 
//				ll x = 0, j = i;
//	            while (j < s.size() && isdigit(s[j])){
//	                x = x * 10 + s[j] - '0';
//	                j++;
//	            }
//	            cout<<j<<endl;
//	            nums.push(x); 
//	            i = j - 1;
			//还原 说明这个数字已经到了第几位了  指向数字的下一个位置  为什么减去一捏
			/*ex  1000+10  
			 	i=0  j=0
			 	j=1  x=1
			 	j=2 x=10
			 	j=3 x=100
			 	j=4 x=1000
			 	
			 	i=j-1 i=3指向1000最后面一个0  然后该if条件跳出  大循环里i++ 
			 */ 
		//也可以用字符串来处理 
			 ll x=0,j=i;
			 while(j<s.size()&&isdigit(s[j]))
			 	j++;
			string ts=s.substr(i,j);
			x=stol(ts); 
			nums.push(x); 
			i=j-1;
			 
		}
		if(s[i]=='('){
			ops.push(s[i]);  //这里m中没有定义但是 默认{{'(',0}}; 
		}
		if(s[i]==')'){
			while(ops.top()!='(')  caculate();	
			ops.pop();
		}
		if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/'){
			//为什么是while   自己推一遍1+5*2+4  
			while(ops.size()&&m[ops.top()] >= m[s[i]]) //当且仅当栈顶的元素优先级比 入栈op低的时候才会op入栈 else 先计算 
				caculate();
			ops.push(s[i]); 
		}
	}
	 while (ops.size()) caculate();//剩余的进行计算
    cout << nums.top() << endl;//输出结果
}


可能出现的问题:

              问题一:当数字是1001 时候该如何读入数据栈中?

  代码中的注释有两种方法,一种用数学,二用string 去处理的。

              问题二:四则运算的规则怎么实现的?

根据是否在栈中和+ -,* / ,的运算顺序 来划分优先级

             问题三:括号如何处理的?

       如果是( 我们直接放入栈中 ,如果)的话那么我们开始倒出操作栈中的操作符直到是(为止

                             

        

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值