/*由式子生成二叉树*/
//例如输入:1-2.2*5+4*3/(5+6)-7*8
#include<stdio.h>
#include<sys/malloc.h>
#include<stdlib.h>
//
//定义数据结构
#define MaxSize 50
typedef union {
char ch;
double db;
} two_type_data;
typedef struct{
int b;//指示是数字还是运算符,如果是数字为0,如果是运算符,也用来区分是同类中是第几个运算
int pri;
two_type_data data;
}Array;
typedef struct BitNode{
//ElemType data;
Array data;
struct BitNode *lchild,*rchild;
}BitNode,*BiTree;
//
void Print(Array A[],int length){
int i=0;
while(i<length){
if(A[i].b)
printf("%c",A[i].data.ch);
else
printf("%f",A[i].data.db);
i++;
}
printf("\n");
}
int ToInOrder(Array A[],Array B[],int length){
//将式子转化为中序,即效果上是去除括号
int i=0,k=0;
for(i=0;i<length;i++)
if(A[i].data.ch!='(' && A[i].data.ch!=')')
B[k++]=A[i];
return k;
}
int ToPostOrder(Array A[],Array C[],int length){
int i=0,k=0;
Array D[MaxSize];//栈
int top=-1,temp;
for(i=0;i<length;i++){
if(A[i].b!=0){//判断是否是运算符
temp=A[i].pri;
if(top!=-1){
while(top!=-1 && D[top].pri>temp)
C[k++]=D[top--];//出栈
if(top!=-1 && D[top].pri==temp){
top--;//出栈‘(’并且舍弃‘)’
continue;
}
}
D[++top]=A[i];//入栈
switch(A[i].data.ch){//修改栈内优先级
case '+':D[top].pri=3;break;
case '-':D[top].pri=3;break;
case '*':D[top].pri=5;break;
case '/':D[top].pri=5;break;
case '(':D[top].pri=1;break;
case ')':D[top].pri=6;break;
}
}
else
C[k++]=A[i];//如果是数字,直接输出
}
while(top!=-1)//出栈
C[k++]=D[top--];
return k;
}
BiTree PostInCreateTree(Array A[],Array B[],int l1,int h1,int l2,int h2){//由中序和后序来构造树,l1,h1为最小下标和最大下标
int i=0,llen=0,rlen=0;
BiTree T=(BiTree)malloc(sizeof(BitNode));
T->data=A[h1];//A为后序
for(i=l2;i<h2;i++)
if(B[i].data.db==A[h1].data.db && B[i].b==A[h1].b)
break;//B为中序
if(i<h2){
llen=i-l2;
rlen=h2-i;
}
if(llen)
T->lchild=PostInCreateTree(A,B,l1,l1+llen-1,l2,l2+llen-1);
else
T->lchild=NULL;
if(rlen)
T->rchild=PostInCreateTree(A,B,h1-rlen,h1-1,h2-rlen+1,h2);
else
T->rchild=NULL;
return T;
}
BiTree PreInCreateTree(Array A[],Array B[],int l1,int h1,int l2,int h2){//由中序和先序来构造树,l1,h1为最小下标和最大下标
int i=0,llen=0,rlen=0;
BiTree T=(BiTree)malloc(sizeof(BitNode));
T->data=A[l1];//A为先序
for(i=l2;i<h2;i++)
if(B[i].data.db==A[l1].data.db && B[i].b==A[l1].b)
break;//B为中序
if(i<h2){
llen=i-l2;
rlen=h2-i;
}
if(llen)
T->lchild=PreInCreateTree(A,B,l1+1,l1+llen,l2,l2+llen-1);
else
T->lchild=NULL;
if(rlen)
T->rchild=PreInCreateTree(A,B,h1-rlen+1,h1,h2-rlen+1,h2);
else
T->rchild=NULL;
return T;
}
void InOrder(BiTree T){//中序遍历,验证生成的树是否正确
if(T){
InOrder(T->lchild);
if(T->data.b==0)
printf("%f",T->data.data.db);
else
printf("%c",T->data.data.ch);
InOrder(T->rchild);
}
}
double Calculate(BiTree T){//利用树的遍历来求解
double l=0,r=0;
if(T){
l=Calculate(T->lchild);
r=Calculate(T->rchild);
if(T->data.b!=0)
switch(T->data.data.ch){
case '+':return l+r;
case '-':return l-r;
case '*':return l*r;
case '/':return l/r;
default : break;
}
else return T->data.data.db;
}
return 0.0;
}
double Calculate2(Array A[],int length){//利用后序序列求解
Array D[MaxSize];//栈
int top=-1,i=0;
for(i=0;i<length;i++)
if(A[i].b==0)
D[++top]=A[i];
else
switch(A[i].data.ch){
case '+':D[top-1].data.db+=D[top].data.db;top--;break;
case '-':D[top-1].data.db-=D[top].data.db;top--;break;
case '*':D[top-1].data.db*=D[top].data.db;top--;break;
case '/':D[top-1].data.db/=D[top].data.db;top--;break;
default : break;
}
return D[top].data.db;
}
void Reverse(Array A[],Array B[],int length){
int i=0;
for(i=0;i<length;i++) B[i]=A[length-i-1];
}
void ReverseTree(BiTree T){
BiTree temp;
if(T){
ReverseTree(T->lchild);
ReverseTree(T->rchild);
temp=T->lchild;
T->lchild=T->rchild;
T->rchild=temp;
}
}
int FormulaToPre(Array A[],Array C[],int length){
Array B[MaxSize];
Reverse(A,C,length);
Array D[MaxSize];//栈
int top=-1,i=0,k=0,temp;
for(i=0;i<length;i++){
if(C[i].b!=0){//判断是否是运算符
if(C[i].data.ch==')'){//‘)’直接入栈
D[++top]=C[i];
continue;
}
if(C[i].data.ch=='('){//出栈,直到‘)’,并将')'与'('丢弃
while(D[top].data.ch!=')')
B[k++]=D[top--];//出栈
top--;
continue;
}
temp=C[i].pri;
if(top!=-1){
while(top!=-1 && D[top].pri>temp)
B[k++]=D[top--];//出栈
}
D[++top]=C[i];//入栈
}
else
B[k++]=C[i];//如果是数字,直接输出
}
while(top!=-1)//出栈
B[k++]=D[top--];
Reverse(B,C,k);
return k;
}
//主函数
int main(){
//输入并处理;
char ch=0;
double temp,result=0,result2=0;
int index=0,q1=1,q2=1,q3=1,q4=1,q5=1,q6=1;
int lenB=0,lenC=0;
Array A[MaxSize],B[MaxSize],C[MaxSize];
Array B1[MaxSize],C1[MaxSize];
Array D[MaxSize];
int lenD;
BiTree T,T2,T3;
while(1){
scanf("%c",&ch);
if(ch>=48 && ch<=57){//连续输入数字成多位数
temp=ch-48;
while(1){
scanf("%c",&ch);
if(ch>=48 && ch<=57)
temp=temp*10+ch-48;
else if(ch=='.'){//输入小数点
double power=0.1;
double dotnum=0.0;
while(1){
scanf("%c",&ch);
if(ch>=48 && ch<57){
dotnum+=(ch-'0')*power;
power*=0.1;
}
else break;
}
temp+=dotnum;
}
if(!(ch>='0' && ch<='9'))
break;
}
A[index].data.db=temp;
printf("%f\n",temp);
A[index].b=0;//指示数字
index++;
}
switch(ch){
case '+':A[index].data.ch=ch;A[index].b=q1++;A[index].pri=2;index++;break;
case '-':A[index].data.ch=ch;A[index].b=q2++;A[index].pri=2;index++;break;
case '*':A[index].data.ch=ch;A[index].b=q3++;A[index].pri=4;index++;break;
case '/':A[index].data.ch=ch;A[index].b=q4++;A[index].pri=4;index++;break;
case '(':A[index].data.ch=ch;A[index].b=q5++;A[index].pri=6;index++;break;
case ')':A[index].data.ch=ch;A[index].b=q6++;A[index].pri=1;index++;break;
default :break;
}
if(ch=='\n') break;
}
Print(A,index);
lenB=ToInOrder(A,B,index);//转为树的中序
Print(B,lenB);
lenC=ToPostOrder(A,C,index);//转为树的后序
Print(C,lenC);
//法一:中序+后序=====>二叉树
T=PostInCreateTree(C,B,0,lenC-1,0,lenB-1);//生成二叉树
InOrder(T);
result=Calculate(T);
printf("\n%f\n",result);
result2=Calculate2(C,lenC);
printf("%f\n",result2);
//法二:中序->中序1,后序->先序:中序1+先序====>二叉树,再反转二叉树即为所求二叉树
Reverse(B,B1,lenB);//得到中序
Reverse(C,C1,lenC);//得到先序
T2=PreInCreateTree(C1,B1,0,lenC-1,0,lenB-1);
ReverseTree(T2);
InOrder(T2);
printf("\n");
//法三:式子转先序、中序,直接由先序和中序生成二叉树
//首先是中序转先序算法
lenD=FormulaToPre(A,D,index);//得到先序
printf("%d %d\n",lenD,lenB);
Print(D,lenD);
T3=PreInCreateTree(D,B,0,lenD-1,0,lenB-1);
InOrder(T3);
printf("\n");
return 0;
}
由数字式子生成对应的二叉树
最新推荐文章于 2022-10-23 14:11:40 发布