个人知道的有俩种解法
1、渐降解析法,弄不好容易出错,不太推荐,参看华为机试-2014
2、逆波兰式的方法。将中序表达式转成后序!((Reverse Polishnotation,RPN)
逆波兰式的规则如下:参见:http://www.cnblogs.com/stay-foolish/archive/2012/04/25/2470590.html
(1)首先,需要分配2个栈,栈s1用于临时存储运算符(含一个结束符号),此运算符在栈内遵循越往栈顶优先级越高的原则;栈s2用于输入逆波兰式,为方便起见,栈s1需先放入一个优先级最低的运算符,在这里假定为'#';
(2)从中缀式的左端开始逐个读取字符x,逐序进行如下步骤:
1.若x是操作数,则分析出完整的运算数(在这里为方便,用字母代替数字),将x直接压入栈s2;
2.若x是运算符,则分情况讨论:
若x是'(',则直接压入栈s1;
若x是')',则将距离栈s1栈顶的最近的'('之间的运算符,逐个出栈,依次压入栈s2,此时抛弃'(';
若x是除'('和')'外的运算符,则再分如下情况讨论:
若当前栈s1的栈顶元素为'(',则将x直接压入栈s1;
若当前栈s1的栈顶元素不为'(',则将x与栈s1的栈顶元素比较,若x的优先级大于栈s1栈顶运算符优先级,则将x直接压 入栈s1。否者(小于等于),将栈s1的栈顶运算符弹出,压入栈s2中,直到栈s1的栈顶运算符优先级别低于(不包括等 于)x的优先级,或栈s2的栈顶运算符为'(',此时再则将x压入栈s1;
(3)在进行完(2)后,检查栈s1是否为空,若不为空,则将栈中元素依次弹出并压入栈s2中(不包括'#');
(4)完成上述步骤后,栈s2便为逆波兰式输出结果。但是栈s2应做一下逆序处理,因为此时表达式的首字符位于栈底;
以下为代码:
#include <iostream>
#include <string>
#include <stack>
using namespace std;
string rpn_str(string &str);
int calculate(string &str);
bool error_my = false;
int main()
{
string str,str_res;
int res ;
cin>>str;
str_res = rpn_str(str);
if (str_res.size() > 0)
{
cout<< "calculate ";
res = calculate(str_res);
}
else
{
error_my = true;
}
if (error_my )
{
cout<<"false"<<endl;
}
else
{
cout<<res<<endl;
}
return 0;
}
string rpn_str(string &str)
{
if (str.empty())
{
return string("");
}
stack<char> op;
stack<char> res;
op.push('#');
int i = 0;
while(str[i] != '\0')
{
if (str[i] >= '0' && str[i] <= '9')
{
res.push(str[i]);
i++;//下标增加
continue;
}
switch (str[i])
{
case '(':
op.push('(');
break;
case '+':
case '-':
{
char ch = op.top();
while(ch == '+'||ch == '-'||ch == '*'||ch == '/')
{
op.pop();
res.push(ch);
ch = op.top();//再取栈顶
}
op.push(str[i]);
}
break;
case '*':
case '/':
{
char ch = op.top();
while(ch == '*'||ch == '/')
{
op.pop();
res.push(ch);
ch = op.top();//再取栈顶
}
op.push(str[i]);
}
break;
case ')':
{
char ch = op.top();
while(ch != '(' && ch != '#')
{
op.pop();
res.push(ch);
ch = op.top();//再取栈顶
}
if (ch != '(')
{
return string("");
}
op.pop();
}
break;
default:
return string("");
break;
}
i++;//下标增加
}
while(op.size() > 1)
{
res.push(op.top());
op.pop();
}
string final(res.size(),'0');
int k = res.size();
while(!res.empty())
{
final[k-1] = res.top();
k--;
res.pop();
}
return final;
}
int calculate(string &str)
{
error_my = false;
if (str.size() == 0)
{
error_my = true;
return -1;
}
cout<<str<<endl;
stack<int> temp_stack;
int i =0;
int left,right;
while(i < str.size())
{
if (str[i] >= '0' &&str[i] <= '9' )
{
temp_stack.push(str[i]-'0');
i++;
continue;
}
switch(str[i])
{
case '+':
if (temp_stack.size() < 2)
{
error_my = true;
return -1;
}
right = temp_stack.top();
temp_stack.pop();
left = temp_stack.top();
temp_stack.pop();
temp_stack.push(left+right);
break;
case '-':
if (temp_stack.size() < 2)
{
error_my = true;
return -1;
}
right = temp_stack.top();
temp_stack.pop();
left = temp_stack.top();
temp_stack.pop();
temp_stack.push(left-right);
break;
case '*':
if (temp_stack.size() < 2)
{
error_my = true;
return -1;
}
right = temp_stack.top();
temp_stack.pop();
left = temp_stack.top();
temp_stack.pop();
temp_stack.push(left*right);
break;
case '/':
if (temp_stack.size() < 2)
{
error_my = true;
return -1;
}
right = temp_stack.top();
temp_stack.pop();
if (right == 0)//除数不为0
{
error_my = true;
return -1;
}
left = temp_stack.top();
temp_stack.pop();
temp_stack.push(left/right);
break;
}
i++;
}
if (temp_stack.size() == 1)
{
return temp_stack.top();
}
else
{
error_my = true;
return -1;
}
}