对于初学二叉树的读者来说,想要牢牢的记住二叉树的创建算法,就应该踏踏实实的理解算法中每个步骤的含义。
在学二叉树的创建之前,我们需要掌握指针的知识。
指针在二叉树的创建中主要起到数据正常传出自定义函数的作用。
为什么指针具备该作用呢。话不多说直接上代码:
#include
void swap(int,int);//交换函数
int main()
{
int a = 1, b = 2;
swap(a, b);
printf("%d %d", a, b);
return 0;
}
void swap(int a, int b)
{
int temp;
temp = a;
a = b;
b = temp;
}
此代码最终的输出结果为1, 2,这时可能有读者会疑问为什么不是2,1呢? 这里还要提及自定义函数的知识点,在函数体中会自动创建形参对应的变量的复制,也就是说在swap函数中创建了a和b对应的复制变量,函数体内只是对复制变量进行值的交换,因此主函数中的a,b的值不会进行交换。
为了保证主函数中的a,b能真正的进行交换,我们需要引入指针。
#include
void swap(int *,int *);//交换函数
int main()
{
int a = 1, b = 2;
swap(&a, &b);//地址指向对应的变量,所以地址为指针变量。
printf("%d %d", a, b);
return 0;
}
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
将形参改为变量对的指针后运行代码,我们可以发现主函数中的变量进行了交换。函数还是将传入的变量进行了复制,但复制的变量为一个地址,该地址指向一个变量,将两个地址所指向的变量进行交换。
主函数中a,b的地址传入到swap函数中,因此a,b的值进行了交换(一个地址只能指向一个变量)。
typedef struct node{
char data;
struct node *lchild, *rchild;
}Tree;
typedef Tree* BTree;//对该结构体的指针进行重命名;
二叉树依照带虚结点序列创建的基本框架如下:
//测试例子:
//ABDG##H###CE#I##F##
void CreateBTree(BTree *T)
{
char ch;
scanf("%c",&ch);
if(ch=='#'){//说明无结点了。
*T = NULL;
}else{
*T = (BTree)malloc(sizeof(Tree));
if(T==NULL){//判断动态课间是否分配成功;
printf("error!\n");
return ;
}
(*T)->data = ch;
CreateBTree(&(*T)->lchild);//向左遍历创建,传入的实参为指向(*T)->lchild的指针;
CreateBTree(&(*T)->rchild);//向右遍历创建, 传入的实参为指向(*T)->rchild的指针;
}
}
T的类型为BTree的指针, 为什么不是传入BTree类型的T呢?假设我们传入的是BTree类型的T,也就是Tree结构体的指针,在函数中的一系列操作会改变地址值(malloc或赋值为NULL),该复制得到的指针值发生了改变,但仅仅是复制得到的指针值发生改变,函数外传入的指针值并未发生改变,因此为了保证地址的改变量能够正常的传出到函数外,我们就要引入该指针对应的指针(一个地址只能指向一个变量),最终使得传入的变量受影响。
如果题目提供的是先序序列和中序列的话,创建二叉树的算法会稍微复杂一些。
对应框架如下:
//测试例子:
//PRO:ABDGEHCF
//INO:DGBHEAFC
void CreateTree(Tree *T,char *PRO,char *INO,int n)
{
int m=0;
if(n==0){
*T=NULL;
}else{
*T=(Tree)malloc(sizeof(TreeNode));
if(*T==NULL){//判断动态分配是否成功;
printf("Error!\n");
return ;//未成功返回空;
}
(*T)->data=PRO[0];
while(PRO[0]!=INO[m]){
m++;
}
CreateTree(&(*T)->lchild,PRO+1,INO,m);//向左遍历创建对应左孩子;
CreateTree(&(*T)->rchild,PRO+m+1,INO+m+1,n-m-1);//向右遍历创建对应右孩子;
}
}
向左遍历创建对应左孩子的递归代码中PRO+1就等于是PRO[0+1],其对应的地址加一,对先序序列向后一位继续遍历。对应的当前根节点位于中序序列的中间,所以传入INO,m为左孩子的所有结点个数(通过循环遍历到INO的中间根节点的位置,可求出m,m为当前左孩子的个数)。
向右遍历创建对应右孩子的递归代码中PRO+m+1对应在先序序列中当前二叉树的第一个右孩子的对应位置,INO+m+1对应在中序序列中当前二叉树的第一个右孩子的对应位置。
如果题目提供的是后序序列和中序列的话,只需要对上述的框架做一点修改,还是可以得到对应的代码。
1.在创建二叉树的函数中指针主要起到的作用为保证变量值的改变。
2.在创建二叉树时要先观察题目提供的序列,再选择出对应的框架。
3.通过三种遍历方式来检验二叉树是否创建成功。