版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ACdreamers/article/details/46431285
本文的主要内容是如何求一个给定的表达式的值,具体思路就是先将普通算术的中缀表达式转化为后缀表达式,这一步用到的算法叫做调度场算法。然后对后缀表达式,也就是逆波兰表达式求值。
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3596
代码:(参考别人的重构)
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stack>
#include <map>
#define N 10005
#define EPS 1e-9
using namespace std;
struct Node
{
double val;
char opt;
Node(double val = 0, char opt = ' ')
{
this->val = val;
this->opt = opt;
}
};
Node node[N];
char str[N];
map<char, int> mp;
void Init()
{
mp['('] = 0;
mp['-'] = mp['+'] = 1;
mp['*'] = mp['/'] = 2;
mp['^'] = 3;
}
//逆波兰表达式的计算
double CalPoland(Node node[], int n)
{
stack<double> s;
for(int i = 0; i < n; i++)
{
if(node[i].opt == ' ')
s.push(node[i].val);
else
{
double a = s.top();
s.pop();
double b = s.top();
s.pop();
switch(node[i].opt)
{
case '+':
s.push(b + a);
break;
case '-':
s.push(b - a);
break;
case '*':
s.push(b * a);
break;
case '/':
if(fabs(a) < EPS)
throw true;
s.push(b / a);
break;
case '^':
s.push(pow(b, a));
break;
}
}
}
return s.top();
}
//调度场算法
double ShuntYardAlgo(char str[])
{
stack<char> oper;
//inNum标记当前是否可以输入数字
bool inNum = true;
//hasDot标记是否已经输入小数点
bool hasDot = true;
int p = 0; //扫描指针位置
int cnt = 0; //符号或者数字计数器
int sign = 1; //表示正负符号
while(str[p])
{
if(isdigit(str[p]) || str[p] == '.')
{
if(inNum)
{
double val = 0;
double w = 1;
if(str[p] == '.')
{
hasDot = true;
val = 0;
}
else
{
hasDot = false;
val = str[p] - '0';
}
p++;
while(isdigit(str[p]) || str[p] == '.')
{
if(str[p] == '.')
{
if(hasDot) throw true;
hasDot = true;
}
else
{
if(hasDot)
{
w *= 0.1;
val += (str[p] - '0') * w;
}
else
val = val * 10 + str[p] - '0';
}
p++;
}
p--;
node[cnt++] = Node(val * sign, ' ');
sign = 1;
inNum = false;
}
else throw true;
}
else
{
switch(str[p])
{
case '(':
oper.push(str[p]);
break;
case ')':
while(!oper.empty() && oper.top() != '(')
{
node[cnt++] = Node(0, oper.top());
oper.pop();
}
if(oper.empty())
throw true;
oper.pop();
break;
case '+':
case '-':
case '*':
case '/':
case '^':
if(inNum)
{
if(str[p] != '+' && str[p] != '-')
throw true;
while(str[p] == '+' || str[p] == '-')
{
if(str[p] == '-')
sign *= -1;
p++;
}
p--;
}
else
{
while(!oper.empty() && mp[str[p]] <= mp[oper.top()])
{
node[cnt++] = Node(0, oper.top());
oper.pop();
}
oper.push(str[p]);
inNum = true;
}
break;
}
}
p++;
}
while(!oper.empty())
{
node[cnt++] = Node(0, oper.top());
oper.pop();
}
return CalPoland(node, cnt);
}
int main()
{
Init();
while(scanf("%s", str) != EOF)
{
try{
printf("%.8lf\n", ShuntYardAlgo(str));
}
catch(bool){
puts("The teacher is so lazy!");
}
}
return 0;
}