在说明之前,先来看一个栗子:
1 //前略 2 typedef struct Node { 3 int data; 4 struct Node *lchild, *rchild; 5 } *BiTree; 6 void CreateBiTree (BiTree *T) 7 { 8 char ch; 9 scanf("%c", &ch); 10 if (ch == '#') 11 *T = NULL; 12 else 13 { 14 *T = (BiTree)malloc(sizeof(Node)); //分配空间 15 if (!*T) //如果分配失败 16 exit(OVERFLOW); //内存溢出 17 (*T)->data = ch; 18 CreateBiTree(&(*T)->lchild); //用(*T)->lchild作为新的T,下同 19 CreateBiTree(&(*T)->rchild); 20 } 21 }
这是一个二叉链表的实现,(#表示空树)CreateBiTree的参数是BiTree *T,也就是struct Node ** T,那么,为什么要用这个二级指针参数呢?直接BiTree T不好吗?
当然不行(-- _ --),回想一下,就跟变量一样,当你要在一个函数中修改主函数的变量时,需要用到指向这个变量的指针,这样子才能真正的修改变量,而同样的,在二叉链表里面,我们需要修改的就是结构指针(的指向),以此来实现链表,因此,我们需要一个二级结构指针,来修改结构指针的指向。
那么这里有一个误区,有人认为,自己一开始修改的是T,然后是T->lchild和T->rchild, 再然后是T->lchild->lchild ..... ... ,其实不然,你一直都在修改T,每当一个T修改完成,就会把下一个地址(比方说T->lchild) 重新作为T,然后继续修改。
以上。
PS:如果有点懵的话,这里有一个简单的理解方法,那就是你把一级指针看成节点,二级指针看成一级指针,这样子,如果我们要修改节点(A)地址区指向的下一个节点(B),那么就要修改这个原本指向NULL的指针(一级),再然后更新一波指针,即把原来存在于(A)而指向于(B)的指针又变成NULL(原来从A指向B的指针当然存在,只是你这时候无法通过当前指针访问到而已)。