如有不对,不吝赐教
进入正题:
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如2+3*(7-4)+8/4的前缀表达式是:+ + 2 * 3 - 7 4 / 8 4。请设计程序计算前缀表达式的结果值。
输入格式:
输入在一行内给出不超过30个字符的前缀表达式,只包含+、-、*、/以及运算数,不同对象(运算数、运算符号)之间以空格分隔。
输出格式:
输出前缀表达式的运算结果,保留小数点后1位,或错误信息ERROR。
输入样例:
+.+ 2 * 3 - 7 4 / 8 4
输出样例:
13.0
这道题目由中缀表达式求前缀表达式,我们只要构造一棵前缀树,然后在利用前缀树进行计算就可以了,需要注意的就是数字的处理,有非个位数的数字以及可能有负数。
下面给代码:
#include<stdio.h>
#include<malloc.h>
int flag; //表示是否有错误
struct SuffixTree{
int flag; //该节点是否为数字节点
char sign;
double number;
struct SuffixTree *left,*right;
}; //前缀树
double Atof(char *str);
struct SuffixTree *Insert(struct SuffixTree *root,double number,char sign);
double Cal(double num1,double num2,char sign);
void Free(struct SuffixTree *root);
int main(void)
{
int i,j;
char input[31];
char number[31];
double result;
struct SuffixTree *root;
root=(struct SuffixTree *)malloc(sizeof(struct SuffixTree));
root->left=root->right=NULL;
root->flag=-1;
fgets(input,30,stdin);
for(i=0;'\n'!=input[i]&&input[i]&&!flag;){
if(' '==input[i]){
i++;
continue;
}
j=0;
if((('-'==input[i]||'+'==input[i])&&' '!=input[i+1])||(input[i]>='0'&&input[i]<='9')){
while(' '!=input[i]&&input[i]&&'\n'!=input[i])
number[j++]=input[i++];
number[j]='\0';
result=Atof(number);
root=Insert(root,result,'\0');
}
if(input[i]&&' '!=input[i]&&'\n'!=input[i]){
root=Insert(root,-1,input[i]);
i++;
}
}
if(!root->flag||flag)
printf("ERROR");
else
printf("%.1lf",root->number);
Free(root);
return 0;
}
double Atof(char *str)
{
double result=0;
double point=0.1;
int flag;
int i=0;
if('-'==str[0]){
flag=-1;
i++;
}
else if('+'==str[0]){
flag=1;
i++;
}
else
flag=1;
while(str[i]&&'.'!=str[i]){
result=result*10+(str[i]-'0');
i++;
}
while(str[i]){
if('.'==str[i]){
i++;
continue;
}
result+=(str[i]-'0')*point;
point/=10;
i++;
}
return result*flag;
}
struct SuffixTree *Insert(struct SuffixTree *root,double number,char sign)
{
struct SuffixTree *newOne;
newOne=(struct SuffixTree *)malloc(sizeof(struct SuffixTree));
if(sign){
newOne->sign=sign;
newOne->flag=0;
}
else{
newOne->number=number;
newOne->flag=1;
}
newOne->right=newOne->left=NULL;
if(-1==root->flag){
root->flag=newOne->flag;
if(root->flag)
root->number=number;
else
root->sign=sign;
free(newOne);
newOne=NULL;
return root;
}
if(!root->left){
root->left=newOne;
return root;
}
else if(!root->left->flag){
root->left=Insert(root->left,number,sign);
free(newOne);
newOne=NULL;
return root;
} //只用左节点没数据(因为是先填左节点 那么右节点肯定没数据)
//或者左节点存的不是符号 (那么左子树必定有空缺可以填入数据计算出值)
//如果对左节点进行了操作 那么右节点肯定没有数据 因而可以返回
if(!root->right)
root->right=newOne;
else{
if(root->right->flag){
flag=1;
return NULL;
} //表明左右子节点存储的都是数据 还要存一个数据 那么表达式错误
else{
root->right=Insert(root->right,number,sign);
free(newOne);
newOne=NULL;
}
} //对右节点进行计算
if(!root->right){
flag=1;
return NULL;
} //表明右节点出现错误
if(root->right->flag){
root->number=Cal(root->left->number,root->right->number,root->sign);
root->flag=1;
free(root->left);
free(root->right);
root->left=NULL;
root->right=NULL;
}
return root;
}
double Cal(double num1,double num2,char sign)
{
double result;
if('+'==sign)
result=num1+num2;
else if('-'==sign)
result=num1-num2;
else if('*'==sign)
result=num1*num2;
else{
if(!num2){
flag=1;
result=0;
}
else
result=num1/num2;
}
return result;
}
void Free(struct SuffixTree *root)
{
if(!root)
return ;
if(root->left)
free(root->left);
if(root->right)
free(root->right);
free(root);
root=NULL;
return ;
}
结果: