最近学到二叉树,在递归创建二叉树时遇到了点问题,记录一下
二叉树的存储结构:
/****** 二叉树 ********/
typedef struct BiTree{
char data; //数据段
struct BiTree * lchild;
struct BiTree * rchild;
}BiTree;
书上面是每次递归调用的时候读取一个字符作为输入,我改了一下,通过一个字符串去创建。
第一个版本:
void ProOrderInputTree(char * input, BiTree * T)
{
if(*input == 0)
return;
if(*input == '#')
{
T = NULL;//扩展标志
}
else
{
T = (BiTree*)malloc(sizeof(BiTree));
T->data = *input;
ProOrderInputTree(input + 1, T->lchild);
ProOrderInputTree(input + 2, T->rchild);
}
}
思路很简单,把字符串第一个字符作为根的数据,第二个作为左孩子的数据,第三个作为右孩子的数据。
但想一想之后发现不行,创建左子树返回后,input是从栈拿出来的,指向的位置不会变。而左子树的子孙个数是不一定的。
于是我想到设置一个全局变量,指向当前结点的数据,它不是函数内的局部变量,不会进栈:
char* c;
void ProOrderInputTree(char * input, BiTree * T)
{
c = input;
if(*c== 0)
return;
if(*c== '#')
{
c++;
T = NULL;
}
else
{
T = (BiTree*)malloc(sizeof(BiTree));
T->data = *c;
c++;
ProOrderInputTree(c, T->lchild);
ProOrderInputTree(c, T->rchild);
}
}
修改后发现还是不行,调试的时候发现,每次递归完后,T的左右孩子指向了无法访问的内存,这就很疑惑,每次传入的都是指针,为什么还是无法改变呢?
在网上找了一圈,终于理解了,简单来说,当使用malloc创建内存时,函数参数T的值改变了,导致它的双亲无法找到它了。(经典的值传递无法改变变量的问题,只不过这次的‘值’是地址而已)
知道原因就简单了,通过二级指针传递:
char * c;
void ProOrderInputTree(char * input, BiTree ** T)
{
c = input;
if(*c == 0)
return;
if(*c == '#')
{
c++;
*T = NULL;
}
else
{
(*T) = (BiTree*)malloc(sizeof(BiTree));
(*T)->data = *c;
c++;
ProOrderInputTree(c, &(*T)->lchild);
ProOrderInputTree(c, &(*T)->rchild);
}
}
这样就可以实现了