【AcWing】 3302. 表达式求值

博客围绕表达式求值问题展开,给定含 +,-,*,/ 运算符及括号的表达式,需计算最终值。介绍了输入输出格式、数据范围,重点阐述思路,采用双栈(操作数栈和运算符栈),依据运算符优先级处理,还给出代码样例。
  1. 表达式求值

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

注意:
在这里插入图片描述

输入格式

共一行,为给定表达式。

输出格式

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

数据范围

表达式的长度不超过 105。

输入样例:

(2+2)*(1+1)

输出样例:

8

思路:

“表达式求值问题:,两个要点:
①双栈,一个操作数栈,一个运算符栈
②运算符优先级,栈顶运算符和即将入栈的运算符的优先级比较:
如果栈顶的运算符优先级低,新运算符就直接入栈
如果栈顶的运算符优先级高,先出栈计算,新运算符再入栈

代码样例:

#include<bits/stdc++.h>
using namespace std;

stack<int> num;
stack<char> op;

//优先级表
unordered_map<char,int> h{{'+',1},{'-',1},{'*',2},{'/',2}};

void eval()//求值
{
	int a=num.top();//第二个操作数
	num.pop();
	
	int b=num.top();//第一个操作数
	num.pop();
	
	char p=op.top();//运算符
	op.pop();
	
	int r=0;//结果
	
	//计算结果
	if(p=='+') r=a+b;
	if(p=='-') r=b-a;
	if(p=='*') r=b*a;
	if(p=='/') r=b/a;
	
	num.push(r);//结果入栈 
 } 
 
 int main()
 {
 	string s;//读入表达式
	 cin>>s;
	 
	 for(int i=0;i<s.size();i++)
	 {
	 	if(isdigit(s[i]))//数字入栈 
	 	{
	 		int x=0,j=i;//计算数字
			 while(j<s.size()&&isdigit(s[j]))
			 {
			 	x=x*10+s[j]-'0';
			 	j++;
			  } 
			  num.push(x);//数字入栈
			  i=j-1; 
		 }
		 //左括号无优先级,直接入栈
		 else if(s[i]=='(')//左括号入栈
		 {
		 	op.push(s[i]);
		  } 
		  //括号特殊,遇到左括号直接入栈,遇到右括号计算括号里面的
		  else if(s[i]==')')
		  {
		  	while(op.top()!='(')//一直计算到左括号
			  eval();
			op.pop();//左括号出栈 
		   } 
		   else
		   {
		   	while(op.size()&&h[op.top()]>=h[s[i]])//待入栈运算符优先级低,则先计算
			   eval();
			op.push(s[i]);//操作符入栈 
			} 
	  } 
	  while(op.size()) eval();//剩余的进行计算
	  cout<<num.top()<<endl;//输出结果
	  return 0; 
  } 
### ACWing 表达式求值算法实现 表达式求值是一种经典的栈操作问题,通常涉及两个栈:一个是用于存储数字的 `num` 栈,另一个是用于存储运算符的 `op` 栈。以下是基于引用中的描述和标准方法来实现该算法的过程。 #### 算法核心逻辑 1. **初始化** 创建两个栈分别用来保存数字 (`num`) 和运算符 (`op`)。 2. **处理字符流** 遍历整个字符串,逐个解析字符并执行相应操作: - 如果遇到的是数字,则将其转换为整型数值后压入 `num` 栈[^1]。 - 如果遇到左括号 `'('`,则直接压入 `op` 栈[^3]。 - 如果遇到右括号 `')'`,则弹出 `op` 栈顶运算符并与 `num` 栈顶元素进行计算,直到匹配到最近的一个左括号为止。 - 如果遇到运算符(如 `+`, `-`, `*`, `/`),则先判断其优先级是否大于等于当前栈顶运算符的优先级;如果是,则将栈顶运算符取出并完成一次计算后再继续处理新运算符。 3. **结束条件** 当遍历完成后,如果 `op` 栈中仍有剩余运算符,则依次弹出这些运算符并对 `num` 栈中的对应数字做进一步计算,直至 `op` 栈为空。 4. **返回结果** 计算结束后,`num` 栈应只剩下一个元素即为最终的结果。 --- #### Python 实现代码 以下是一个完整的 Python 版本实现: ```python def precedence(op): """定义运算符优先级""" if op == '+' or op == '-': return 1 elif op == '*' or op == '/': return 2 return 0 def apply_operation(a, b, op): """应用二元运算符""" if op == '+': return a + b elif op == '-': return a - b elif op == '*': return a * b elif op == '/': return int(a / b) def evaluate(expression): num_stack = [] # 存储数字 op_stack = [] # 存储运算符 i = 0 # 字符串索引指针 while i < len(expression): char = expression[i] if char.isdigit(): # 处理多位数字 value = 0 while i < len(expression) and expression[i].isdigit(): value = (value * 10) + int(expression[i]) i += 1 num_stack.append(value) continue elif char == '(': op_stack.append(char) elif char == ')': while op_stack[-1] != '(': operator = op_stack.pop() b = num_stack.pop() a = num_stack.pop() result = apply_operation(a, b, operator) num_stack.append(result) op_stack.pop() # 移除对应的左括号 '(', 不参与后续计算 elif char in "+-*/": while (len(op_stack) > 0 and precedence(op_stack[-1]) >= precedence(char)): operator = op_stack.pop() b = num_stack.pop() a = num_stack.pop() result = apply_operation(a, b, operator) num_stack.append(result) op_stack.append(char) i += 1 # 剩余部分计算 while len(op_stack) > 0: operator = op_stack.pop() b = num_stack.pop() a = num_stack.pop() result = apply_operation(a, b, operator) num_stack.append(result) return num_stack[0] # 测试用例 expression1 = "((7*8)+(9-7))/((12-6)-(6-3))" expression2 = "7*8/4+5*7-3/2" print(evaluate(expression1)) # 输出: 10 print(evaluate(expression2)) # 输出: 41 ``` --- #### 关键点说明 1. 运算符优先级通过函数 `precedence()` 定义,确保高优先级运算符能够提前被处理。 2. 使用辅助函数 `apply_operation()` 来简化不同运算符的具体实现细节。 3. 对于连续多个数字的情况,在检测到第一个数字时进入循环读取完整数值再加入 `num` 栈。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值