关于二叉树的建立(C语言)(链式)

      首先,我们得知道二叉树是什么!!这东西网上一大把。

      还有,二叉树的遍历顺序,前序(根左右),中序(左根右),后序(左右根)一般用递归来实现,而层序用队列(先父亲进,然后父亲出,接着儿子进,以此类推)。

而今天我要讲的是二叉树的建立需要主要谈指针和结构体,还有typedef吧!

     第一是结构体和typedef吧;

typedef char ElemType;
typedef struct BitNode
{
    ElemType date;
    struct BitNode *lChild,*rChild;
    
}Bitnode;
typedef char ElemType;
typedef struct BitNode
{
    ElemType date;
    struct BitNode *lChild,*rChild;
    
}BTree;

这两种方法都行!

里面的struct BitNode *lChild,*rChild;之所以不报错是因为外面的typedef struct BitNode,加了一个typedef之后这个结构就相当于有了自己的独有身份,自己也可以使用自己(用于构建自己的左右子树),也可以向外延伸比如Bitnode;,BTree;也可以使用指针类型的如*tree;啊等等,在其他函数中可以使用你向外延伸的身份了,如果非要用你原来的身份的话,那就得按照C语言结构体的声明方法使用了(跟建二叉树的左右子树一样)。

    第二是创建二叉树的主要函数:

void builtTree(BTree **root){
    char ch;
    
    scanf("%c",&ch);
    if(ch=='#'){
        *root=NULL;
        return ;
    }
    else 
    {
    *root=(BTree *)malloc(sizeof(BTree));
    (*root)->date=ch;
    }
    builtTree(&((*root)->lChild));
    builtTree(&((*root)->rChild));
}

这里呢,我使用的是我朋友教我的二级指针。为什么要这样使用?因为你要想啊!你的左右子树都是指针,你干嘛不是指针。而一级指针是可以在其他封装函数修改指针指向的变量值的,而二级指针则是修改指针指向的指针(地址)。这也是在之后递归创建左右子树埋下扎实的种子(模板)。

if(ch=='#'){
        *root=NULL;
        return ;
    }

这一步,我时常会忘掉写return;没有return的话,它会默认继续创建子树,造成无限递归,也就造成二叉树的建立失败。还有这里是 *root=NULL;,而为什么不是**root,就跟你用一级指针的时候一样,当你使用的有*的时候你可以修改里面的值,而你不使用*的时候,它总会联系到指针这方面去,你的目的是修改指针指向的指针,而为什么不用root,同样你的目的是修改指针指向的指针。

还有啊,我们应该都知道&这是取地址符,这个*是取值符;而root是指向*root的指针(已经定义的情况下),*root是指向**root的指针。

看似有点绕,其实还真的有点绕,谁叫指针学起来就是有点绕。你也可以直接写一个返回指针

 else 
    {
    *root=(BTree *)malloc(sizeof(BTree));
    (*root)->date=ch;
    }

使用#include <stdlib.h>的头文件,开拓空间给*root,(sizeof(BTree))这个是说给你多少空间,(BTree *)这是将你创建出来的东西强制转化类型,加个*表示为指针类型。

    builtTree(&((*root)->lChild));
    builtTree(&((*root)->rChild));

这是根据先序(左根右)的方式进行创建二叉树的。还有要使用&取孩纸指针的地址(原理和根结点一样)。

第三是遍历二叉树的函数(前序遍历)

void PreOrderTraverse(BTree *T, int level)
{
    if (T)
    {
        vist(T->date, level);
        PreOrderTraverse(T->lChild, level + 1);
        PreOrderTraverse(T->rChild, level + 1);
    }
}

上面已经把指针指向设置好了,现在只需要使用它就完事了,我选择使用一级指针而不用二级指针,是不想杀鸡用牛刀而已。你也可以用。

void PreOrderTraverse(BTree **T, int level)
{
    if (*T)
    {
        vist((*T)->date, level);
        PreOrderTraverse(&((*T)->lChild), level + 1);
 
        PreOrderTraverse(&((*T)->rChild), level + 1);
    }
}

第三是打印函数

void vist(char c, int level)
{
    printf("%c位于%d层\n", c, level);
}

封装函数好处多多,不过参数传的要准确对应,不然会脑阔疼

最后全代码是

#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
typedef struct BitNode
{
    ElemType date;
    struct BitNode *lChild,*rChild;
    
}BTree;
void builtTree(BTree **root){
    char ch;
    
    scanf("%c",&ch);
    if(ch=='#'){
        *root=NULL;
        return ;
    }
    else 
    {
    *root=(BTree *)malloc(sizeof(BTree));
    (*root)->date=ch;
    }
    builtTree(&((*root)->lChild));
    builtTree(&((*root)->rChild));
}
void vist(char c, int level)
{
    printf("%c位于%d层\n", c, level);
}
void PreOrderTraverse(BTree *T, int level)//一级指针 
{
    if (T)
    {
        vist(T->date, level);
        PreOrderTraverse(T->lChild, level + 1);
        PreOrderTraverse(T->rChild, level + 1);
    }
}
//void PreOrderTraverse(BTree **T, int level)
//{
//    if (*T)
//    {
//        vist((*T)->date, level);
//        PreOrderTraverse(&((*T)->lChild), level + 1);
// 
//        PreOrderTraverse(&((*T)->rChild), level + 1);
//    }
//}
int main()
{
	printf("请输入二叉树的各个结点以字符‘# ’为空子树,当你输入一棵完整的二叉树后它自然会打印:\n");
	int level = 1;
    BTree **tree;
    builtTree(&tree);
      //  PreOrderTraverse(&tree, level);//二级指针
		  PreOrderTraverse(tree, level);
    return 0;
}

你还可以用

#include <stdio.h>
#include <stdlib.h>
typedef struct BitNode
{
    char data;//结点数据 
    struct BitNode *lChild, *rChild;//指向左右子树的指针 
} BitNode, *Bittree;//对应变量的名称 
void CreateBitree(Bittree *T)//默认按照先序遍历的方式存储树 
{
    char c;
    scanf("%c", &c);
    if ('#' == c)//当c为#时,为空 
    {
        *T = NULL;
    }
    else
    {
        *T = (BitNode *)malloc(sizeof(BitNode));
        (*T)->data = c;
        CreateBitree(&(*T)->lChild);
        CreateBitree(&(*T)->rChild);
    }
}
void vist(char c, int level)
{
    printf("%c位于%d层\n", c, level);
}
void PreOrderTraverse(Bittree T, int level)
{
    if (T)
    {
        vist(T->data, level);
        PreOrderTraverse(T->lChild, level + 1);
        PreOrderTraverse(T->rChild, level + 1);
    }
}
int main()
{
    int level = 1;
    Bittree T = NULL;
    CreateBitree(&T);
    PreOrderTraverse(T, level);

    return 0 ;
}

两者都行,或者其他逻辑和我的差不多。要么就用数组的方法.

最后·,希望这东西对您有用。

猜你喜欢

转载自blog.csdn.net/m0_51538049/article/details/123566054