给定一个包含正整数、加(+)、减(-)、乘()、除(/)的算数表达式(括号除外),计算其结果。
表达式仅包含非负整数,+, - ,,/ 四种运算符和空格 。 整数除法仅保留整数部分。
示例 1:
输入: “3+2*2” 输出: 7
示例 2:
输入: " 3/2 " 输出: 1
示例 3:
输入: " 3+5 / 2 " 输出: 5
说明:
你可以假设所给定的表达式都是有效的。请不要使用内置的库函数 eval。
思路:先将中缀表达式 转换为后缀表达式,然后再利用后缀表达式求值。
问题就困难在 如何将中缀表达式转换为后缀表达式?
' '
,这里其实要注意使用while循环
读入运算数,因为运算数有不是1位数的情况,读入完整运算数后再在其后加空格 。同样地 在ecalculateRPN
函数模块中读取运算数时也应该注意,使用while循环
将字符转换为整型>
栈顶运算符 压入栈中<=
栈顶运算符 将栈顶运算符弹出并输出到结果数组中,其后加 ' '
。再比较新的栈顶运算符 直到该运算符优先级>
栈顶运算符为止然后将该运算符压入栈。' '
。ecalculateRPN
模块中对运算数和运算符的判定添加便利#include
#include
#include
#include
#include
#include
using namespace std;
int calculate(string s);
vector<char> toRPN(string s);//注意这里 是把后缀表达式存储为 char类型的vector数组中,不再是Leetcode150题中的string 类型。方便后续比较不同运算符中的优先级 (用swtich语句)
int checkPriority(char ch);
int calculateRPN(vector<char> tokens);
int main()
{
string s;
getline(cin,s);
int ans=calculate(s);
cout << ans <<endl;
return 0;
}
int calculate(string s) {
vector<char>later;
later=toRPN(s);
for(int i=0;i<later.size();i++)
{
cout << later[i];
}
cout <<endl;
return calculateRPN(later);
}
int checkPriority(char ch)
{
switch(ch)
{
case '+': return 1;
case '-': return 1;
case '*': return 2;
case '/': return 2;
default: return 0;
}
}
vector<char> toRPN(string s)
{
vector<char> s1; //存储转换后的后缀表达式
stack<char> op; //存储等待中的运算符号
for(int i = 0; i < s.size(); ++i)
{
//输入的字符串中可能包含空格 要跳过
if(s[i] == ' ') continue;
//如果遇到的是运算符 则需要判断它的优先级 与 当前栈顶的运算符的优先级
if(s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/')
{
if(op.empty())
op.push(s[i]);
else
{
if(checkPriority(s[i]) > checkPriority(op.top()))
op.push(s[i]);
else
{
while(!op.empty() && (checkPriority(s[i]) <= checkPriority(op.top())))
{
s1.push_back(op.top());
s1.push_back(' ');
op.pop();
}
op.push(s[i]);
}
}
}
else if(s[i]>='0' && s[i]<='9')//如果遇到运算数直接放进 s1
{
while(s[i]>='0' && s[i]<='9')
{
s1.push_back(s[i]);
++i;
}
s1.push_back(' ');
--i;
}
}
while(!op.empty())
{
s1.push_back(op.top());
s1.push_back(' ');
op.pop();
}
return s1;
}
int ecalculateRPN(vector<char> tokens)
{
stack<int> data;
int sz = tokens.size();
for(int i = 0; i < sz; ++i){
if(tokens[i]=='+'){
int b = data.top();
data.pop();
int a = data.top();
data.pop();
data.push(a+b);
}
else if(tokens[i]=='-'){
int b = data.top();
data.pop();
int a = data.top();
data.pop();
data.push(a-b);
}
else if(tokens[i]=='*'){
int b = data.top();
data.pop();
int a = data.top();
data.pop();
data.push(a*b);
}
else if(tokens[i]=='/'){
int b = data.top();
data.pop();
int a = data.top();
data.pop();
data.push(a/b);
}
else if(tokens[i]>='0' && tokens[i]<='9')
{
int tmp=tokens[i]-'0';
int j=++i;
while(tokens[j]>='0' && tokens[j]<='9')
{
tmp=tmp*10+(tokens[j]-'0');//要加括号 不然可能会越界
++j;
}
data.push(tmp);
i=--j;
}
}
return data.top();
}
其实就是在中缀表达式 转后缀表达式的过程中增加对括号的判定:
#include
#include
#include
#include
#include
#include
using namespace std;
int calculate(string s);
vector<char> toRPN(string s);
int checkPriority(char ch);
int calculateRPN(vector<char> tokens);
int main()
{
string s;
getline(cin,s);
int ans=calculate(s);
cout << ans <<endl;
return 0;
}
int calculate(string s) {
vector<char>later;
later=toRPN(s);
for(int i=0;i<later.size();i++)
{
cout << later[i];
}
cout <<endl;
return calculateRPN(later);
}
int checkPriority(char ch)
{
switch(ch)
{
case '+': return 1;
case '-': return 1;
case '*': return 2;
case '/': return 2;
default: return 0;
}
}
vector<char> toRPN(string s)
{
vector<char> s1; //存储转换后的后缀表达式
stack<char> op; //存储等待中的运算符号
for(int i = 0; i < s.size(); ++i)
{
//如果遇到空格 跳过
if(s[i] == ' ') continue;
if(s[i] == '(')
{
op.push(s[i]);
}
if(s[i] == ')')
{
while(!op.empty() && op.top()!='(')
{
s1.push_back(op.top());
s1.push_back(' ');
op.pop();
}
op.pop();//将栈顶的左括号弹出
}
//如果遇到的是运算符 则需要判断它的优先级 与 当前栈顶的运算符的优先级
if(s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/')
{
if(op.empty())
op.push(s[i]);
else
{
if(checkPriority(s[i]) > checkPriority(op.top()))
op.push(s[i]);
else
{
while(!op.empty() && (checkPriority(s[i]) <= checkPriority(op.top())))
{
s1.push_back(op.top());
s1.push_back(' ');
op.pop();
}
op.push(s[i]);
}
}
}
else if(s[i]>='0' && s[i]<='9')//如果遇到运算数直接放进 s1
{
while(s[i]>='0' && s[i]<='9')
{
s1.push_back(s[i]);
++i;
}
s1.push_back(' ');
--i;
}
}
while(!op.empty())
{
s1.push_back(op.top());
s1.push_back(' ');
op.pop();
}
return s1;
}
int calculateRPN(vector<char> tokens)
{
stack<int> data;
int sz = tokens.size();
for(int i = 0; i < sz; ++i){
if(tokens[i]=='+'){
int b = data.top();
data.pop();
int a = data.top();
data.pop();
data.push(a+b);
}
else if(tokens[i]=='-'){
int b = data.top();
data.pop();
int a = data.top();
data.pop();
data.push(a-b);
}
else if(tokens[i]=='*'){
int b = data.top();
data.pop();
int a = data.top();
data.pop();
data.push(a*b);
}
else if(tokens[i]=='/'){
int b = data.top();
data.pop();
int a = data.top();
data.pop();
data.push(a/b);
}
else if(tokens[i]>='0' && tokens[i]<='9')
{
int tmp=tokens[i]-'0';
int j=++i;
while(tokens[j]>='0' && tokens[j]<='9')
{
tmp=tmp*10+(tokens[j]-'0');//要加括号 不然可能会越界
++j;
}
data.push(tmp);
i=--j;
}
}
return data.top();
}