由数字式子生成对应的二叉树

/*由式子生成二叉树*/
//例如输入: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;   
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值