题目链接 :点击查看
题目描述 :
给定一个表达式,其中运算符仅包含 +,-,*,/
(加 减 乘 整除),可能包含括号,请你求出表达式的最终值。
注意:
- 数据保证给定的表达式合法。
- 题目保证符号
-
只作为减号出现,不会作为负号出现,例如,-1+2
,(2+2)*(-(1+1)+2)
之类表达式均不会出现。 - 题目保证表达式中所有数字均为正整数。
- 题目保证表达式在中间计算过程以及结果中,均不超过 2^31−1。
- 题目中的整除是指向 0 取整,也就是说对于大于 00 的结果向下取整,例如 5/3=1,对于小于 00 的结果向上取整,例如 5/(1−4)=−1。
- C++和Java中的整除默认是向零取整;Python中的整除
/
默认向下取整,因此Python的eval()
函数中的整除也是向下取整,在本题中不能直接使用。
输入输出
输入
(2+2)*(1+1)
输出
8
题目分析 :
表达式求值问题一般要考虑三个关键点。(1) 建立双栈, 一个操作数栈,一个运算符栈,实现对表达式的运算(2) 比较即将入栈的运算符和运算符栈栈顶的运算符的优先级。如要入栈的运算符优先级较低,则将操作数和运算符出栈计算。反之,直接将运算符入栈。(3)括号情况。要当前字符是左括号,则直接入运算符栈,要是右括号,则要出栈计算,直到遇到左括号(可以看做是(2)的特殊情况,左括号的优先级为0,右括号单独考虑)。为了方便计算,我们定义一个eval()函数每次调用对栈顶部的两个数与运算符进行操作运算,这里要注意,num栈的栈顶元素是第二操作数(作除数,减数,其他两种运算符则无所谓),弹出之后接下来的数才是第一操作数。详见如下代码。
#include<iostream>
#include<cstdio>
#include<string>
#include<stack>
#include<unordered_map>
#include<cstring>
#include<cstdlib>
#include<cctype>
using namespace std;
stack <int> num;//操作数栈
stack <int> op;//运算符栈
unordered_map<char, int> h{{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}};//用hash表记录运算符的优先级
void eval() {
int a = num.top(); num.pop();//第二个操作数
int b = num.top(); num.pop();//第一个操作数
char p = op.top(); op.pop();//运算符
int res = 0;//结果
if (p == '+') res = b + a;
if (p == '-') res = b - a;
if (p == '*') res = b * a;
if (p == '/') res = b / a;
num.push(res);
}
int main() {
string s;
cin >> s;
for (int i = 0; i < s.size(); i ++ ) {
if (isdigit(s[i])) {//数字入栈
int x = 0, j = i;//x用来记录数字(一位或是多位) j用来记录位置
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;
}
---------------------------------------------------------------------