第十一周-项目二 用二叉树求解代数表达式

来源:互联网 发布:淘宝客推广网站有哪些 编辑:程序博客网 时间:2024/06/05 03:00

问题及描述:

/**烟台大学计算机与控制工程学院作者:郗小艺完成日期:2016年11月10号问题描述:(1)根据形如“1+2*3-4/5”的字符串代表的表达式,构造出对应的二叉树,用后序遍历的思路计算表达式的值时,能体现出先乘除后加减的规则。          (2)对构造出的二叉树,计算出表达式的值。*/#include <stdio.h>#include <malloc.h>#include<string.h>#include <stdlib.h>#define MaxSize 100typedef char ElemType;typedef struct node{    ElemType data;              //数据元素    struct node *lchild;        //指向左孩子    struct node *rchild;        //指向右孩子} BTNode;void CreateBTNode(BTNode *&b,char *str);        //由str串创建二叉链BTNode *FindNode(BTNode *b,ElemType x);     //返回data域为x的节点指针BTNode *LchildNode(BTNode *p);  //返回*p节点的左孩子节点指针BTNode *RchildNode(BTNode *p);  //返回*p节点的右孩子节点指针int BTNodeDepth(BTNode *b); //求二叉树b的深度void DispBTNode(BTNode *b); //以括号表示法输出二叉树void DestroyBTNode(BTNode *&b);  //销毁二叉树void CreateBTNode(BTNode *&b,char *str)     //由str串创建二叉链{    BTNode *St[MaxSize],*p=NULL;    int top=-1,k,j=0;    char ch;    b=NULL;             //建立的二叉树初始时为空    ch=str[j];    while (ch!='\0')    //str未扫描完时循环    {        switch(ch)        {        case '(':            top++;            St[top]=p;            k=1;            break;      //为左节点        case ')':            top--;            break;        case ',':            k=2;            break;                          //为右节点        default:            p=(BTNode *)malloc(sizeof(BTNode));            p->data=ch;            p->lchild=p->rchild=NULL;            if (b==NULL)                    //p指向二叉树的根节点                b=p;            else                            //已建立二叉树根节点            {                switch(k)                {                case 1:                    St[top]->lchild=p;                    break;                case 2:                    St[top]->rchild=p;                    break;                }            }        }        j++;        ch=str[j];    }}BTNode *FindNode(BTNode *b,ElemType x)  //返回data域为x的节点指针{    BTNode *p;    if (b==NULL)        return NULL;    else if (b->data==x)        return b;    else    {        p=FindNode(b->lchild,x);        if (p!=NULL)            return p;        else            return FindNode(b->rchild,x);    }}BTNode *LchildNode(BTNode *p)   //返回*p节点的左孩子节点指针{    return p->lchild;}BTNode *RchildNode(BTNode *p)   //返回*p节点的右孩子节点指针{    return p->rchild;}int BTNodeDepth(BTNode *b)  //求二叉树b的深度{    int lchilddep,rchilddep;    if (b==NULL)        return(0);                          //空树的高度为0    else    {        lchilddep=BTNodeDepth(b->lchild);   //求左子树的高度为lchilddep        rchilddep=BTNodeDepth(b->rchild);   //求右子树的高度为rchilddep        return (lchilddep>rchilddep)? (lchilddep+1):(rchilddep+1);    }}void DispBTNode(BTNode *b)  //以括号表示法输出二叉树{    if (b!=NULL)    {        printf("%c",b->data);        if (b->lchild!=NULL || b->rchild!=NULL)        {            printf("(");            DispBTNode(b->lchild);            if (b->rchild!=NULL) printf(",");            DispBTNode(b->rchild);            printf(")");        }    }}void DestroyBTNode(BTNode *&b)   //销毁二叉树{    if (b!=NULL)    {        DestroyBTNode(b->lchild);        DestroyBTNode(b->rchild);        free(b);    }}//用s[i]到s[j]之间的字符串,构造二叉树的表示形式BTNode *CRTree(char s[],int i,int j){    BTNode *p;    int k,plus=0,posi;    if (i==j)    //i和j相同,意味着只有一个字符,构造的是一个叶子节点    {        p=(BTNode *)malloc(sizeof(BTNode));   //分配存储空间        p->data=s[i];                         //值为s[i]        p->lchild=NULL;        p->rchild=NULL;        return p;    }    //以下为i!=j的情况    for (k=i; k<=j; k++)        if (s[k]=='+' || s[k]=='-')        {            plus++;            posi=k;              //最后一个+或-的位置        }    if (plus==0)                 //没有+或-的情况(因为若有+、-,前面必会执行plus++)        for (k=i; k<=j; k++)            if (s[k]=='*' || s[k]=='/')            {                plus++;                posi=k;            }    //以上的处理考虑了优先将+、-放到二叉树较高的层次上    //由于将来计算时,运用的是后序遍历的思路    //处于较低层的乘除会优先运算    //从而体现了“先乘除后加减”的运算法则    //创建一个分支节点,用检测到的运算符作为节点值    if (plus!=0)    {        p=(BTNode *)malloc(sizeof(BTNode));        p->data=s[posi];                //节点值是s[posi]        p->lchild=CRTree(s,i,posi-1);   //左子树由s[i]至s[posi-1]构成        p->rchild=CRTree(s,posi+1,j);   //右子树由s[poso+1]到s[j]构成        return p;    }    else       //若没有任何运算符,返回NULL        return NULL;}double Comp(BTNode *b){    double v1,v2;    if (b==NULL)        return 0;    if (b->lchild==NULL && b->rchild==NULL)  //叶子节点,应该是一个数字字符(本项目未考虑非法表达式)        return b->data-'0';    //叶子节点直接返回节点值,结点中保存的数字用的是字符形式,所以要-'0'    v1=Comp(b->lchild); //先计算左子树    v2=Comp(b->rchild); //再计算右子树    switch(b->data)     //将左、右子树运算的结果再进行运算,运用的是后序遍历的思路    {    case '+':        return v1+v2;    case '-':        return v1-v2;    case '*':        return v1*v2;    case '/':        if (v2!=0)            return v1/v2;        else            abort();    }}int main(){    BTNode *b;    char s[MaxSize]="1+2*3-4/5";    printf("代数表达式%s\n",s);    b=CRTree(s,0,strlen(s)-1);    printf("对应二叉树:");    DispBTNode(b);    printf("\n表达式的值:%g\n",Comp(b));    DestroyBTNode(b);    return 0;}


运行结果:



学习心得:

能很大的节省空间。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 最近鼻涕和痰多怎么办 鼻涕痰多怎么办没感冒 一岁宝宝痰多怎么办 小孩鼻涕和痰多怎么办 鼻子老长鼻屎要怎么办 眼睛老有眼屎是怎么办 眼睛有干眼屎是怎么办 小孩流黄鼻涕是怎么办 孕妇9个月流鼻涕怎么办 流黄鼻涕两周了怎么办 大人流黄脓鼻涕怎么办 鼻子一直流鼻涕像水一样怎么办 6个月婴儿流鼻涕怎么办 9个月婴儿流鼻涕怎么办 狗狗晕车吐了怎么办 小狗又拉又吐怎么办 犬瘟热流黄鼻涕怎么办 2个月幼犬流鼻涕怎么办 5个月宝宝流鼻血怎么办 1岁宝宝感冒鼻塞怎么办 4个月宝宝鼻塞怎么办 4岁宝宝感冒鼻塞怎么办 宝宝4个月流鼻涕怎么办 3个月的宝宝鼻塞怎么办 50天的小孩鼻塞怎么办 鼻子流脓鼻涕2周怎么办 两岁宝宝流清鼻涕怎么办 1岁宝宝流黄鼻涕怎么办 宝宝上火流黄鼻涕怎么办 一周岁宝宝流清鼻涕怎么办 一周岁流清鼻涕怎么办 4岁宝宝感冒发烧怎么办 6个月宝宝流鼻涕怎么办 8岁儿童感冒发烧怎么办 婴儿感冒咳嗽怎么办%3f 小孩流鼻涕鼻塞怎么办最简单方法 宝宝鼻炎鼻子不通气怎么办 小孩晚上睡觉鼻子不通气怎么办 孩子晚上睡觉鼻子不通气怎么办 3个月婴儿流鼻涕怎么办 一个月宝宝鼻塞流鼻涕怎么办