本题来源:《算法竞赛入门》第11章11.11.2
本题给的解法:
核心代码:
int build_tree(string exp,int l,int r)
{
cout<<"l="<<l<<"\tr="<<r<<endl;
int c1,c2,p,u;
c1=-1;
c2=-1;
p=0;
if(r-l<=1)
{
u=++cnt;
chl[u]=chr[u]=0;
operation[u]=exp[x];
return -1;
}
for(int i=l;i<r;++i)
{
switch(exp[i])
{
case '(':++p;break;
case ')':--p;break;
case '+': case '-': if(!p)c1=i;break;
case '*': case '/': if(!p)c2=i;break;
}
}
if(c1<0)
c1=c2;
if(c1<0)
return build_tree(exp,l+1,r-1);
u=++cnt;
chl[u]=build_tree(exp,l,c1);
chr[u]=build_tree(exp,c1+1,r);
operation[u]=exp[c1];
return u;
}
我为了让这个代码对我更加友好写,对这个代码做了一下修改,改完之后的完整代码是这样的:
#include<iostream>
#include<fstream>
#include<string>
#include<cstring>
using namespace std;
ifstream fin("ExpressionTree.in");
#define MAXSIZE 100
string exp;
int chl[MAXSIZE],chr[MAXSIZE];
char operation[MAXSIZE];
int cnt=0;
int build_tree(string exp,int l,int r)
{
cout<<"l="<<l<<"\tr="<<r<<endl;
int c1,c2,p,u;
c1=-1;
c2=-1;
p=0;
if(r-l<=1)
{
u=++cnt;
chl[u]=chr[u]=-1;
operation[u]='#';
return -1;
}
for(int i=l;i<r;++i)
{
switch(exp[i])
{
case '(':++p;break;
case ')':--p;break;
case '+': case '-': if(!p)c1=i;break;
case '*': case '/': if(!p)c2=i;break;
}
}
if(c1<0)
c1=c2;
if(c1<0)
return build_tree(exp,l+1,r-1);
u=++cnt;
chl[u]=build_tree(exp,l,c1);
chr[u]=build_tree(exp,c1+1,r);
operation[u]=exp[c1];
return u;
}
int main()
{
memset(operation,0,sizeof(operation));
memset(chl,0,sizeof(operation));
memset(chr,0,sizeof(operation));
fin>>exp;
build_tree(exp,0,exp.size());
for(int i=1;i<=cnt;++i)
cout<<operation[i]<<"\t";
cout<<endl;
return 0;
}
改完之后我为了实现这个代码的完整功能,借着个算法提出了个目标:输入一个数学表达式,输出答案。然后对上面的核心代码进行修改,添加我需要的计算功能,删除我不需要的储存功能,就写出了下面的完整程序:
#include<iostream>
#include<fstream>
#include<string>
#include<cstring>
using namespace std;
ifstream fin("../Data/CalExp.in");
#define MIN -32767
string str;
int result;
int checkVadality(int val,int l,int r)
{
if(val==MIN)
{
val=0;
for(int i=l;i<r;++i)
if(str[i]>='0'&&str[i]<='9')
val=val*10+(str[i]-'0');
}
return val;
}
int calc(string s,int l,int r)
{
int c1=-1,c2=-1,p=0;
int s1=0,s2=0;
if(r-l<=1)
{
return MIN;
}
for(int i=l;i<r;++i)
{
switch(s[i])
{
case '(':++p;break;
case ')':--p;break;
case '+': case '-':if(!p)c1=i;break;
case '*': case '/':if(!p)c2=i;break;
}
}
if(c1<0)
c1=c2;
if(c1<0)
{
return calc(s,l+1,r-1);
}
s1=calc(s,l,c1);
s2=calc(s,c1+1,r);
s1=checkVadality(s1,l,c1);
s2=checkVadality(s2,c1+1,r);
if(s[c1]=='+')
{
return s1+s2;
}
else if(s[c1]=='-')
{
return s1-s2;
}
else if(s[c1]=='*')
{
return s1*s2;
}
else if(s[c1]=='/')
{
return s1/s2;
}
}
int main()
{
while(cin>>str)
cout<<calc(str,0,str.size());
return 0;
}
这样一个完整的,具备初级加减乘除功能的计算器程序就实现了。
然后我发现,这个算法和我之前写过的一个有相似之处。Complicated Expression。这个代码可以用这个算法来替换。