最近正复习专业课,到创建二叉树这里忽然掉链子了。原因无他,全是指针干的。话不多说,先上一份代码,观其形。
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真麻烦,尤其是写博客的时候....嘤嘤嘤