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

本文介绍了一种使用括号表示法构建二叉树的方法,并实现了递归遍历算法,包括先序、中序和后序遍历。此外,还提供了一个具体的示例程序,演示如何利用这些函数构建并显示一个简单的代数表达式二叉树。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[csharp]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. /*  
  2.  *Copyright (c) 2016,烟台大学计算机学院  
  3.  *All rights reserved.  
  4.  *文件名称:btree.cpp  
  5.  *作者:衣龙川  
  6.  *完成日期:2016年11月10日  
  7.  *版本号:vc++6.0  
  8.  *  
  9.  *问题描述:二叉树遍历的递归算法  
  10.  *输入描述:无  
  11.  *程序输出:二叉树先序中序后序遍历  
  12. */    

[csharp]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. btree.h  
  2. #ifndef BTREE_H_INCLUDED  
  3. #define BTREE_H_INCLUDED  
  4.  
  5. #define MaxSize 100  
  6. typedef char ElemType;  
  7. typedef struct node  
  8. {  
  9.     ElemType data;              //数据元素  
  10.     struct node *lchild;        //指向左孩子  
  11.     struct node *rchild;        //指向右孩子  
  12. } BTNode;  
  13. void CreateBTNode(BTNode *&b,char *str);        //由str串创建二叉链  
  14. BTNode *FindNode(BTNode *b,ElemType x);     //返回data域为x的节点指针  
  15. BTNode *LchildNode(BTNode *p);  //返回*p节点的左孩子节点指针  
  16. BTNode *RchildNode(BTNode *p);  //返回*p节点的右孩子节点指针  
  17. int BTNodeDepth(BTNode *b); //求二叉树b的深度  
  18. void DispBTNode(BTNode *b); //以括号表示法输出二叉树  
  19. void DestroyBTNode(BTNode *&b);  //销毁二叉树  
  20.  
  21. #endif // BTREE_H_INCLUDED  
[csharp]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. btree.cpp  
  2. #include <stdio.h>  
  3. #include <malloc.h>  
  4. #include "btree.h"  
  5.   
  6. void CreateBTNode(BTNode *&b,char *str)     //由str串创建二叉链  
  7. {  
  8.     BTNode *St[MaxSize],*p=NULL;  
  9.     int top=-1,k,j=0;  
  10.     char ch;  
  11.     b=NULL;             //建立的二叉树初始时为空  
  12.     ch=str[j];  
  13.     while (ch!='\0')    //str未扫描完时循环  
  14.     {  
  15.         switch(ch)  
  16.         {  
  17.         case '(':  
  18.             top++;  
  19.             St[top]=p;  
  20.             k=1;  
  21.             break;      //为左节点  
  22.         case ')':  
  23.             top--;  
  24.             break;  
  25.         case ',':  
  26.             k=2;  
  27.             break;                          //为右节点  
  28.         default:  
  29.             p=(BTNode *)malloc(sizeof(BTNode));  
  30.             p->data=ch;  
  31.             p->lchild=p->rchild=NULL;  
  32.             if (b==NULL)                    //p指向二叉树的根节点  
  33.                 b=p;  
  34.             else                            //已建立二叉树根节点  
  35.             {  
  36.                 switch(k)  
  37.                 {  
  38.                 case 1:  
  39.                     St[top]->lchild=p;  
  40.                     break;  
  41.                 case 2:  
  42.                     St[top]->rchild=p;  
  43.                     break;  
  44.                 }  
  45.             }  
  46.         }  
  47.         j++;  
  48.         ch=str[j];  
  49.     }  
  50. }  
  51. BTNode *FindNode(BTNode *b,ElemType x)  //返回data域为x的节点指针  
  52. {  
  53.     BTNode *p;  
  54.     if (b==NULL)  
  55.         return NULL;  
  56.     else if (b->data==x)  
  57.         return b;  
  58.     else  
  59.     {  
  60.         p=FindNode(b->lchild,x);  
  61.         if (p!=NULL)  
  62.             return p;  
  63.         else  
  64.             return FindNode(b->rchild,x);  
  65.     }  
  66. }  
  67. BTNode *LchildNode(BTNode *p)   //返回*p节点的左孩子节点指针  
  68. {  
  69.     return p->lchild;  
  70. }  
  71. BTNode *RchildNode(BTNode *p)   //返回*p节点的右孩子节点指针  
  72. {  
  73.     return p->rchild;  
  74. }  
  75. int BTNodeDepth(BTNode *b)  //求二叉树b的深度  
  76. {  
  77.     int lchilddep,rchilddep;  
  78.     if (b==NULL)  
  79.         return(0);                          //空树的高度为0  
  80.     else  
  81.     {  
  82.         lchilddep=BTNodeDepth(b->lchild);   //求左子树的高度为lchilddep  
  83.         rchilddep=BTNodeDepth(b->rchild);   //求右子树的高度为rchilddep  
  84.         return (lchilddep>rchilddep)? (lchilddep+1):(rchilddep+1);  
  85.     }  
  86. }  
  87. void DispBTNode(BTNode *b)  //以括号表示法输出二叉树  
  88. {  
  89.     if (b!=NULL)  
  90.     {  
  91.         printf("%c",b->data);  
  92.         if (b->lchild!=NULL || b->rchild!=NULL)  
  93.         {  
  94.             printf("(");  
  95.             DispBTNode(b->lchild);  
  96.             if (b->rchild!=NULL) printf(",");  
  97.             DispBTNode(b->rchild);  
  98.             printf(")");  
  99.         }  
  100.     }  
  101. }  
  102. void DestroyBTNode(BTNode *&b)   //销毁二叉树  
  103. {  
  104.     if (b!=NULL)  
  105.     {  
  106.         DestroyBTNode(b->lchild);  
  107.         DestroyBTNode(b->rchild);  
  108.         free(b);  
  109.     }  
  110. }  
[csharp]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. main.cpp
  1. #include <stdio.h>
    #include <string.h>
    #include <malloc.h>
    #include "btree.h"


    //用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;
    }
  1. 运行截图:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值