二叉树的建立(C语言)


 二叉树的建立(C语言)


    对于初学二叉树的读者来说,想要牢牢的记住二叉树的创建算法,就应该踏踏实实的理解算法中每个步骤的含义。

    在学二叉树的创建之前,我们需要掌握指针的知识。

指针

    指针在二叉树的创建中主要起到数据正常传出自定义函数的作用。

    为什么指针具备该作用呢。话不多说直接上代码:

#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.通过三种遍历方式来检验二叉树是否创建成功。

 

你可能感兴趣的