初学二叉树的初始化,为什么一定要定义一个指针型变量

根据视屏教程里的代码,第八行结构后定义了一个(星号)BiTree,但是程序里的所有二级指针变量前都加了取值符合(星号),不知道为什么要定义这个指针型的(星号)BiTree,于是稍作修改,将去掉并且整个程序只有一级指针,但是运行出错
请问原因是什么?

//以下是教学上的正确代码
#include <stdio.h>
#include <stdlib.h>
typedef char elemtype;
typedef struct BiTNode
{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;

//创建一颗二叉树,约定用户用前序遍历方式输入数据 
void createBiTree(BiTree *T)
{
    char c;
    scanf("%c",&c);
    if(' '==c)
    {
        *T=NULL;
    }
    else
    {
        *T=(BiTNode*)malloc(sizeof(BiTNode));
        (*T)->data=c;
        createBiTree(&(*T)->lchild);
        createBiTree(&(*T)->rchild);
    }
} 

void visit(char c,int level)//访问二叉树节点的具体操作 
{
    printf("%c位于第%d层\n",c,level);
}
//前序遍历二叉树
void PreOrderTraverse(BiTree T,int level)
{
    if(T)
    {
        visit(T->data,level);
        PreOrderTraverse(T->lchild,level+1);
        PreOrderTraverse(T->rchild,level+1);
    }
} 

int main(int argc, char *argv[]) {
    int level=1;
    BiTree T=NULL;
    createBiTree(&T); 
    PreOrderTraverse(T,level);
    return 0;
}

//**********************
//**********************
//**********************
//以下为修改后不能正常运行的代码
#include <stdio.h>
#include <stdlib.h>
typedef char elemtype;
typedef struct BiTNode
{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTree; 


void createBiTree(BiTree *T)
{
    char c;
    scanf("%c",&c);
    if(' '==c)
    {
        T=NULL;
    }
    else
    {
        T=(BiTree*)malloc(sizeof(BiTree));
        T->data=c;
        createBiTree(T->lchild);
        createBiTree(T->rchild);
    }
} 

void visit(char c,int level)//访问二叉树节点的具体操作 
{
    printf("%c位于第%d层\n",c,level);
}
//前序遍历二叉树
void PreOrderTraverse(BiTree *T,int level)
{
    if(T)
    {
        visit(T->data,level);
        PreOrderTraverse(T->lchild,level+1);
        PreOrderTraverse(T->rchild,level+1);
    }
} 

int main(int argc, char *argv[]) {
    int level=1;
    BiTree T;
    createBiTree(&T); 
    PreOrderTraverse(&T,level);
    return 0;
}
对于一个函数,你修改参数变量,是不会影响调用者的。比如
void foo(int i)
{
i = 4;
}
int main()
{
int i = 3;
foo(i);
printf("%d", i); //还是3
}
那么要修改i怎么办?需要用指针:
void foo(int * i)
{
*i = 4;
}
int main()
{
int i = 3;
foo(&i);
printf("%d", i); //还是3
}
也就是你可以修改i指向的变量。但是如果你把这个指针同样视作是一个变量,它还是不能修改的。
void foo(int * i)
{
int j = 4;
i = &j; //这里修改的是i本身,而不是i指向的内存。
}
int main()
{
int i = 3;
foo(&i);
printf("%d", i); //还是3
}
而我们初始化的代码,需要在函数内分配内存,让指针指向这个新的地址,并且作用在原来的函数上,这个就要指针的指针。

总结下就是
变量 不能修改值
指针 不能修改指向,可以修改值
指针的指针,不能修改指向的指向,但是可以修改指向的指针
指针的指针的指针,不能修改指向的指向的指向,但是可以修改指向的指向
...
往下可以无限写下去。