**
算术表达式的转换
**
Time Limit: 1000MS Memory limit: 65536K
题目描述
小明在学习了数据结构之后,突然想起了以前没有解决的算术表达式转化成后缀式的问题,今天他想解决一下。
因为有了数据结构的基础小明很快就解出了这个问题,但是他突然想到怎么求出算术表达式的前缀式和中缀式呢?小明很困惑。聪明的你帮他解决吧。
输入
输入一算术表达式,以\’#\’字符作为结束标志。(数据保证无空格,只有一组输入)
输出
输出该表达式转换所得到的前缀式 中缀式 后缀式。分三行输出,顺序是前缀式 中缀式 后缀式。
示例输入
a*b+(c-d/e)*f#
示例输出
+* ab *-c/def
a*b+c-d/e*f
ab*cde/-f*+
提示
来源
示例程序
ps:
参考的刘汝佳的大白书。自己做了好几天sad。今天终于A了
思路:
算术表达式求前中后缀可以先把算数表达式转化成二叉树然后对二叉树进行前中后序遍历。建成的二叉树每个非叶结点表示一个运算符,左子树是第一个运算数对应的表达式,右子树是第二个运算数对应的表达式。给表达式建立表达式树方法很多,这里介绍的是找到“最后计算”的运算符当做整个表达式树的跟,然后递归处理。
AC Code :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int lch[1010],rch[1010];//每个叶子结点的左右子结点编号;
char op[1010];//每个结点的字符;
int cnt=0;//结点数
char s[1010];//字符串
int build(char *s,int x,int y)//x表示字符串的起始地址,y表示结束地址;
{
int i,c1=-1,c2=-1,p=0,u;//c1记录“最右”出现的加减号,c2记录“最右”出现的乘除号,p记录完整的括号,u代表根节点的位置
if(y-x==1)//仅一个字符,建立单独结点
{
u=++cnt;
lch[u]=rch[u]=0;
op[u]=s[x];
return u;
}
/*寻找最后一个运算符,只有当p=0的时候才考虑,因为括号里的运算符一定不是最后计算的,由于加减和乘除是左结合性
所以括号外的最后一个运算符才是最后计算的*/
for(i=x;i<y;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 build(s,x+1,y-1);//把大括号去掉然后递归调用,最后找到最后计算的运算符s[c1]
u=++cnt;
lch[u]=build(s,x,c1);//左子树为[x,c1];
rch[u]=build(s,c1+1,y);//右子树为[c1+1,y];
op[u]=s[c1];
return u;
}
void qianxu(int u)
{
if(u)
{
printf("%c",op[u]);
qianxu(lch[u]);
qianxu(rch[u]);
}
}
void zhongxu(int u)
{
if(u)
{
zhongxu(lch[u]);
printf("%c",op[u]);
zhongxu(rch[u]);
}
}
void houxu(int u)
{
if(u)
{
houxu(lch[u]);
houxu(rch[u]);
printf("%c",op[u]);
}
}
int main()
{
scanf("%s",s);
int len=strlen(s);
int u=build(s,0,len-1);
qianxu(u);
printf("\n");
zhongxu(u);
printf("\n");
houxu(u);
printf("\n");
return 0;
}