一、题目描述
二、解题思路
将中缀表达式转换为后缀表达式。
三、解题代码
class Solution
{
private:
static unordered_map<char, int> icp, isp;
stack<char> stk;
string src;
string sln;
void Back();
int calc(int tmp1, char oper, int tmp2);
public:
int calculate(string str) {
for (size_t i = 0; i < str.size(); i++) // remove space
if (str.at(i) != ' ')
src += str[i];
stk.push('#');
return eval();
}
int eval();
};
unordered_map<char, int> Solution::icp{{'#', 0}, {'(', 6}, {')', 1}, {'*', 4}, {'/', 4}, {'+', 2}, {'-', 2}};
unordered_map<char, int> Solution::isp{{'#', 0}, {'(', 1}, {')', 6}, {'*', 5}, {'/', 5}, {'+', 3}, {'-', 3}};
void Solution::Back()
{
int left = 0, right = 0;
auto len = src.size();
for (; left < len; left++) //双指针法切割字符串
{
if (isdigit(src[left])) //没有正负号的情况进行切割
{
for (right = left; right < len && icp.find(src.at(right)) == icp.end(); right++)
;
sln += src.substr(left, right - left);
sln += " ";
left = right - 1;
}
else
{
auto tmp = src.at(left);
if (tmp == '-' || tmp == '+')
{
//如果开头就是负号,没什么可说的
//或者该操作符前一个位置还是操作符,但是它前面那个操作符不是')'的话,说明它一定为正负号
if (!left || (src.at(left - 1) != ')' && icp.find(src.at(left - 1)) != icp.end()))
{
if (tmp == '-')
sln += tmp;
for (right = ++left; right < len && icp.find(src.at(right)) == icp.end(); right++)
;
sln += src.substr(left, right - left);
sln += " ";
left = right - 1;
continue;
}
}
if (isp[stk.top()] < icp[tmp])
stk.push(tmp);
else // if (isp[stk.top()] > icp[tmp])
{ //必须要把if (isp[stk.top()] > icp[tmp])注释掉,否则无法准确识别正负号,无法通过测试点
while (isp[stk.top()] > icp[tmp])
{
sln += stk.top();
sln += " ";
stk.pop();
}
isp[stk.top()] >= icp[tmp] ? stk.pop() : stk.push(tmp);
}
}
}
while (stk.size() > 1) //切割完成后排空栈
{
sln += stk.top();
sln += " ";
stk.pop();
}
sln = sln.substr(0, sln.size() - 1); //去掉结果串结尾的' '
//cout << sln << endl;
}
int Solution::calc(int first, char oper, int second)
{
int ans;
if (oper == '+')
ans = first + second;
else if (oper == '-')
ans = first - second;
else if (oper == '*')
ans = first * second;
else if (oper == '/'){
if(!second) exit(0);
ans = first / second;
}
else exit(1);
return ans;
}
int Solution::eval()
{
Back();
stack<int> num;
size_t left = 0, right = 0;
auto len = sln.size();
for (; left < len; left++)
{
for (right = left; right < len && sln.at(right) != ' '; right++)
;
if (right - left == 1)
{
if (icp.find(sln.at(left)) != icp.end())
{
auto oper = sln.at(left);
auto second = num.top();
num.pop();
auto first = num.top();
num.pop();
num.push(calc(first, oper, second));
}
else
num.push(sln.at(left) - '0');
}
else
num.push(atoi(sln.substr(left, right - left).c_str()));
left = right;
}
return num.top();
}