二叉树的基本操作(小系统)包含测试数据及错误思想

验证数据:
ab##cd###

具体代码如下

#include <stdio.h>
#include<stdlib.h>

typedef struct node{
    char data;
    struct node *rchild,*lchild;
}BiTNode,*BiTtree;


int count=0;
int leafcount=0;
int depth=0;
void CreateTree(BiTNode **root)
{

    char data;
    scanf("%c",&data);
    if(data == '#')
    {
        (*root)=NULL;
    }

    else
    {
        *root = (BiTNode *)malloc(sizeof(BiTNode));
        if((*root) == NULL)
        {
            printf("分配空间失败!\n");
            exit(0);
        }
        (*root)->data = data;
        CreateTree(&((*root)->lchild));
        CreateTree(&((*root)->rchild));
    }

}

//先序
void preBiTree(BiTtree root){
    if(root!=NULL){
        printf("%c",root->data);
        preBiTree(root->lchild);
        preBiTree(root->rchild);
    }
}
//中序
void InOrder(BiTtree root){
    if(root!=NULL){
        InOrder(root->lchild);   /*中序遍历左子树*/
        printf("%c",root->data); /*输出根节点*/
        InOrder(root->rchild);   /*中序遍历右子树*/
    }
}
//后序
void PostOrder(BiTtree root){
    if(root!=NULL){
        PostOrder(root->lchild);
        PostOrder(root->rchild);
        printf("%c",root->data);
    }
}

//二叉树的复制
BiTtree CopyBTree(BiTtree root){
    BiTtree p,lchild,rchild;
    if(root==NULL)
        return NULL;
    lchild=CopyBTree(root->lchild);
    rchild=CopyBTree(root->rchild);
    p=(BiTtree)malloc(sizeof(BiTNode));
    p->data=root->data;
    p->lchild=root->lchild;
    p->rchild=root->rchild;
    return p;
}

//统计二叉树节点总数
void CountAll(BiTtree root){
//    else
//        return CountAll(root->lchild)+CountAll(root->rchild)+1;
//}
    if(root){
        count++;
        CountAll(root->lchild);
        CountAll(root->rchild);
    }
}
//叶子节点总数
int LeafCount(BiTtree root){
    if(root==NULL)
        return 0;
    if(root->lchild==NULL&&root->rchild==NULL)
        return 1;
    else{
        return LeafCount(root->lchild)+LeafCount(root->rchild);
    }
}
//叶子结点数(法二)
void Leaf(BiTtree root){
    if(root)
    {
        if(root->lchild==NULL&&root->rchild==NULL)leafcount++;
        Leaf(root->lchild);
        Leaf(root->rchild);
        
    }
}

//高度
int PostTreeDepth(BiTtree bt){
    int hl,hr,max;
    if(bt!=NULL){
        hl=PostTreeDepth(bt->lchild);
        hr=PostTreeDepth(bt->rchild);
        max=hl>hr?hl:hr;
        return(max+1);
    }
    return 0;
}
//层次最大值求树的深度
void PreTreeDepth2(BiTtree bt,int h){
    if(bt!=NULL){
        if(h>depth) depth=h;
        PreTreeDepth2(bt->lchild, h+1);
        PreTreeDepth2(bt->rchild, h+1);
    }
}



int main(int argc, const char * argv[]) {
    int sele;

    BiTNode bt;
    BiTtree root=&bt;
    while(1){
        printf("\n1:建立二叉树\n");
        printf("2:前序输出二叉树\n");
        printf("3:中序输出二叉树\n");
        printf("4:后序输出二叉树\n");
        printf("5:二叉树节点总数\n");
        printf("6:二叉树叶子结点数\n");
        printf("7:求二叉树的高度递归算法\n");
        printf("8:层次最大值求二叉树的深度\n");
        printf("0:退出\n");
        scanf("%d",&sele);
        switch (sele) {
            case 1:
                CreateTree(&root);
                printf("创建成功!");
                break;
            case 2:
                preBiTree(root);
                break;
            case 3:
                InOrder(root);
                break;
            case 4:
                PostOrder(root);
                break;
            case 5:
                CountAll(root);
                printf("节点总数为:%d\n", count-2);
                break;
            case 6:
               printf("叶子结点数为:%d\n",LeafCount(root)-1);
                break;
            case 7:
                printf("二叉树高度为:%d\n",PostTreeDepth(root)-1);
                break;
            case 8:
                PreTreeDepth2(root,1);
                printf("二叉树高度为:%d\n",depth-1);
                break;
            default:
                exit(0);
        }
    }
    return 0;
}


//void CreateBiTree(BiTtree *root){//指向指针类型的指针
//    char ch;
//    scanf("%c",&ch);
// //   ch=getchar();
//    if(ch=='@'){
//        (*root)=NULL;
//    }
//    else{
//        *root=(BiTtree)malloc(sizeof(BiTNode));
//        (*root)->data=ch;
//
//        CreateBiTree(&(*root)->lchild);
//        CreateBiTree(&(*root)->rchild);
//
//    }
//}


//先序创建二叉树
//int CreateBiTree(BiTtree *root){
//    char ch;
//    ch=getchar();
//    if(ch=='@') root=NULL;
//    else{
//        *root=(BiTtree)malloc(sizeof(BiTNode));
//        if(!*root) exit(0);
//        (*root)->data=ch;
//        CreateBiTree(&(*root)->lchild);
//        CreateBiTree(&(*root)->rchild);
//    }
//    return 1;
//}

至于为啥测试数据最后
回车后为什么加两个##
我突然想到是不是程序把回车符当作了二叉树的一个结点,需要给出他它的左子树,右子树呢,那这样的话他的深度,结点数,都会发生变化,结点数应该多一个,为什么最后结果是共6个结点,但是之前不做主函数里的switch却可以正常输出?
所以我只能在主函数里面控制
在这里插入图片描述
但是没在主函数里面修改count-2时候结果如下
在这里插入图片描述

困惑了好多天的问题一直没有解决。。

今天重新看创建二叉树时灵光一现,或许程序员总能在某个奇怪的时刻发现问题。。

即 if(data == ‘#’)这个条件,
之前测试时如上图
因为我一直觉着是因为回车符的原因造成了回车之后要重新加两个##来代表回车符的两个左右子树为空。。(也就是把回车符也当做了一个结点),但是我不清楚最后的结果为什么是结点多了两个?所以先从这个回车下手,我修改了条件,改为 if(data<‘a’||data>‘z’)来测试,结果如下:
在这里插入图片描述
此时,我发现,我靠为啥我还没创建,就告诉我创建成功了??
我猜想会不会是根本没有创建,即没有满足更改的if条件?那么只能说明我switch选择1后回车,这个回车符也当做结点来判断了!!
所以,为了这个回车符不被当作结点来判断,我决定在主函数中吃掉它,即char ch;ch=getchar();但是我又尝试了几种位置,到这样:在这里插入图片描述
结果终于如我所愿了!!心情莫名的舒畅。
在这里插入图片描述
所以将之前的主函数里为了凑结点数,深度等的-1,-2等等删掉,恢复最初学的程序结果即可。

#include <stdio.h>
#include<stdlib.h>

typedef struct node{
    char data;
    struct node *rchild,*lchild;
}BiTNode,*BiTtree;


int count=0;
int leafcount=0;
int depth=0;
void CreateTree(BiTNode **root)
{

    char data;
    scanf("%c",&data);
   // if(data == '#')
    if(data<'a'||data>'z')
    {
        (*root)=NULL;
    }

    else
    {
        *root = (BiTNode *)malloc(sizeof(BiTNode));
        if((*root) == NULL)
        {
            printf("分配空间失败!\n");
            exit(0);
        }
        (*root)->data = data;
        CreateTree(&((*root)->lchild));
        CreateTree(&((*root)->rchild));
    }

}

//先序
void preBiTree(BiTtree root){
    if(root!=NULL){
        printf("%c",root->data);
        preBiTree(root->lchild);
        preBiTree(root->rchild);
    }
}
//中序
void InOrder(BiTtree root){
    if(root!=NULL){
        InOrder(root->lchild);   /*中序遍历左子树*/
        printf("%c",root->data); /*输出根节点*/
        InOrder(root->rchild);   /*中序遍历右子树*/
    }
}
//后序
void PostOrder(BiTtree root){
    if(root!=NULL){
        PostOrder(root->lchild);
        PostOrder(root->rchild);
        printf("%c",root->data);
    }
}

//二叉树的复制
BiTtree CopyBTree(BiTtree root){
    BiTtree p,lchild,rchild;
    if(root==NULL)
        return NULL;
    lchild=CopyBTree(root->lchild);
    rchild=CopyBTree(root->rchild);
    p=(BiTtree)malloc(sizeof(BiTNode));
    p->data=root->data;
    p->lchild=root->lchild;
    p->rchild=root->rchild;
    return p;
}

//统计二叉树节点总数
void CountAll(BiTtree root){
//    else
//        return CountAll(root->lchild)+CountAll(root->rchild)+1;
//}
    if(root){
        count++;
        CountAll(root->lchild);
        CountAll(root->rchild);
    }
}
//叶子节点总数
int LeafCount(BiTtree root){
    if(root==NULL)
        return 0;
    if(root->lchild==NULL&&root->rchild==NULL)
        return 1;
    else{
        return LeafCount(root->lchild)+LeafCount(root->rchild);
    }
}
//叶子结点数(法二)
void Leaf(BiTtree root){
    if(root)
    {
        if(root->lchild==NULL&&root->rchild==NULL)leafcount++;
        Leaf(root->lchild);
        Leaf(root->rchild);
        
    }
}

//高度
int PostTreeDepth(BiTtree bt){
    int hl,hr,max;
    if(bt!=NULL){
        hl=PostTreeDepth(bt->lchild);
        hr=PostTreeDepth(bt->rchild);
        max=hl>hr?hl:hr;
        return(max+1);
    }
    return 0;
}
//层次最大值求树的深度
void PreTreeDepth2(BiTtree bt,int h){
    if(bt!=NULL){
        if(h>depth) depth=h;
        PreTreeDepth2(bt->lchild, h+1);
        PreTreeDepth2(bt->rchild, h+1);
    }
}



int main(int argc, const char * argv[]) {
    int sele;
    
    BiTNode bt;
    BiTtree root=&bt;
    while(1){
        printf("\n1:建立二叉树\n");
        printf("2:前序输出二叉树\n");
        printf("3:中序输出二叉树\n");
        printf("4:后序输出二叉树\n");
        printf("5:二叉树节点总数\n");
        printf("6:二叉树叶子结点数\n");
        printf("7:求二叉树的高度递归算法\n");
        printf("8:层次最大值求二叉树的深度\n");
        printf("0:退出\n");
        char ch;
        scanf("%d",&sele);
        ch=getchar();
        switch (sele) {
                
                
            case 1:
                CreateTree(&root);
                printf("创建成功!");
                break;
            case 2:
                preBiTree(root);
                break;
            case 3:
                InOrder(root);
                break;
            case 4:
                PostOrder(root);
                break;
            case 5:
                CountAll(root);
                printf("节点总数为:%d\n", count);
                break;
            case 6:
               printf("叶子结点数为:%d\n",LeafCount(root));
                break;
            case 7:
                printf("二叉树高度为:%d\n",PostTreeDepth(root));
                break;
            case 8:
                PreTreeDepth2(root,1);
                printf("二叉树高度为:%d\n",depth);
                break;
            default:
                exit(0);
        }
    }
    return 0;
}

但是还有一个问题是现在只能是小写字母,我在想。。能不能把最后一个回车也吃掉,恢复最初的 if(data == ‘#’)条件呢?。。

直到我实验把最初的条件改回 if(data == ‘#’),并且下面ch=getchar吃掉了第一个回车符后,最终结果正常显示了,这让我又困惑了,那第二个回车符呢,不用判定去除吗?
直到我上课灵光一现,画出了他们的树状图后才恍然大悟:吃掉第一个回车符,后面的回车符将不会影响了,如图:
在这里插入图片描述
大功告成!
感悟:不亲手写代码,就不会发现其中的细节问题,往往这些细节问题很重要~
加油呀!

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值