C语言指针问题——二叉树的建立

最近正复习专业课,到创建二叉树这里忽然掉链子了。原因无他,全是指针干的。话不多说,先上一份代码,观其形。

typedef char ElemType;
//二叉树的链式存储结构
typedef struct BiTNode{
    ElemType data; //数据域
    struct BiTNode *lchild,*rchild; //左指针域和右指针域
}BiTNode,*BiTree;
void CreateBiTree(BiTree T){
    char data; //树中的值,值若为*时,结束本次创建
    printf("请输入结点值:\n");

    scanf("%c",&data);
    getchar(); //吸收空格

    //*结束标志
    if(data == '*'){
        T = NULL;
        return ;
    }
    T = (BiTree)malloc(sizeof(BiTNode));
    T->data = data; //树中结点赋值
    CreateBiTree(T->lchild);
    CreateBiTree(T->rchild);
}

int main()
{
    BiTree T = NULL;
    CreateBiTree(&T);
    if(T==NULL){
        printf("树为空!\n");
    }
    printf("树的值为:\n");
    PreOrder(T); //先序遍历
    return 0;
}

初步来看,好像没什么问题,先序遍历方式递归创建子树。但是运行结果如下:

这不就尴尬了吗?才到二叉树建立就发现自己能力不足了,sad....

没办法,只好吸收他人之精华,借鉴先人之大道,悟之:

//以先序方式创建
void CreateBiTree(BiTree *T){
    char data; //树中的值,值若为*时,结束本次创建
    BiTree Q;
    printf("请输入结点值:\n");

    scanf("%c",&data);
    getchar(); //吸收空格

    //结束标志
    if(data == '*'){
        *T = NULL;
        return ;
    }
    Q = (BiTree)malloc(sizeof(BiTNode));
    *T = Q;
    Q->data = data; //树中结点赋值
    CreateBiTree(&Q->lchild);
    CreateBiTree(&Q->rchild);
}
int main()
{
    BiTree T = NULL;
    CreateBiTree(&T);
    if(T==NULL){
        printf("树为空!\n");
    }
    printf("树的值为:\n");
    PreOrder(T);
    return 0;
}

结果如下:(图中树的值为a的ASCII码值)


哦哦,完美!

比较前后两个程序,后者使用二维指针进行了操作,而前者只是使用了一维指针。但是但是,为什么会出错呢,指针不是可以直接操作变量值吗?为什么传进去的指针T(指向结点的指针)在子函数里面分配空间后,仍然为空呢?为什么呢?

简单的换个情况测试下,以单链表为例:

typedef int ElemType; //定义表元素的类型
typedef struct LNode{
    ElemType data;
    struct LNode *next;
}LNode,*LinkList;  //LinkeList是指针类型,和LNode*等价
void mal(LinkList L);
void mal(LinkList L){
    L = (LinkList)malloc(sizeof(LNode));
}
int main(){
    LinkList L = NULL;
    mal(L);
    if(L==NULL){
        printf("没有空间!\n");
    }else{
         printf("有空间!\n");
    }
    return 0;
}

结果如下:


哦,还真是这样,指针在子函数里面分配空间,竟然不行...so terrible!

用二维指针试试:

void mal(LinkList *L);
void mal(LinkList *L){
    *L = (LinkList)malloc(sizeof(LNode));
}
int main(){
    LinkList L = NULL;
    mal(&L);
    if(L==NULL){
        printf("没有空间!\n");
    }else{
         printf("有空间!\n");
    }
    return 0;
}

结果如下:


嘿嘿嘿,有了!/xyx (手动滑稽)

故博主推断如下:

无论是指针还是普通变量,在主函数里面初始化后,若想在子函数里直接使用并改变它们的值,都需要借助指针来对它们进行操作,即都需要创建它们地址所对应的指针!

换句话说,int b = 1;add(&b);在 void add(int *a){ *a++; }方法中可以直接改变b的值,但是int b = 1;add(b);在void add(int a){a++}方法中b的值根本不会变。同理:

在主函数中定义了BiTree T = NULL;若想分配空间,创建子树,也需要创建指向BiTree的指针,尽管BiTree是指向结点的指针。故void CreateBiTree(BiTree *T),然后再对*T进行操作,就可以实现二叉树的创建了。

附带一个小例子,自己看吧:

void mal(int **a);
void value(int *b);

void mal(int **a){
    *a = (int *)malloc(sizeof(int));
}

void value(int *a){
    *a = 2;
}

int main(){
    int *a = NULL;
    mal(&a);
    value(a);
    printf("%d",*a);
    return 0;
}

结果当然是能输出2。

顺便吐槽一句,习惯了ctrl s真麻烦,尤其是写博客的时候....嘤嘤嘤

猜你喜欢

转载自blog.csdn.net/gltzlike/article/details/80706423