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