一、引言
前面已经给出了先序法创建二叉树的两种方法,分别是非递归的方法和递归方法,本文将给出了C语言版本的层次法创建二叉树的算法。所谓的层次法其实就是按照二叉树中结点所在的“层”进行遍历,每一层遍历的规则是从左到右。因此层次遍历其实就是按照完全二叉树中结点的编号次序进行遍历的,但是二叉树不一定都是完全二叉树,因此涉及到虚拟的补充成完全二叉树,然后再进行层次遍历。
所使用的示例二叉树如下图所示。
二、二叉树的创建-层次法
1、结点编号规则
层次法创建二叉树,仍旧需要把扩充二叉树。但是此处不同于先序法的扩充的是,需要按照完全二叉树的模式扩充结点。补齐这些结点的目的是为了记录完全二叉树的结点编号而已,因此事实上并不需要真的补齐缺的结点,只需要记住二叉树上所有的结点在完全二叉树上结点的编号即可。
此时,图(1)中结点的编号如下(从1开始):
2、算法的基本思路:
首先创建一个数组S,用于存储二叉树上全部的结点。
之后开始依次读入结点数据,具体做法是一次同时读入某个结点的编号i和数据data,以此创建结点,并把该结点放到数组S的下标为i的位置。接着根据i/2来确定其双亲在S中的下标,且根据i是否被2整除来确定结点i是j的左子树还是右子树。
3、算法的具体实现:
#include"stdio.h"
#include"malloc.h"
#define CHAR
#define MAX_NODE 100
#ifdef CHAR
typedef char datatype;
#else
typedef int datatype;
#endif
typedef struct node
{
datatype data;
struct node *Lchild;
struct node *Rchild;
}BiTree;
BiTree *CreateBiTreeLevel( void )
{
BiTree *T, *p, *s[MAX_NODE];
datatype data;
int i, j;
T = NULL;
while ( 1 )
{
printf( " 输入结点编号( 0 则终止输入 ): " );
scanf( "%d", &i );
if( i == 0 )
break;
else
{
#ifdef CHAR
getchar();//过滤输入结点编号后面的换行符
printf( " 请输入结点数据(字符):" );
scanf( "%c",&data );
getchar();//过滤结点数据后面的换行符
#else
printf( " 请输入结点数据(整数):" );
scanf( "%d",&data );
#endif
//创建结点,并把data存入该结点,同时把该结点的左右子树置空
p = ( BiTree * )malloc( sizeof(BiTree) ) ;
p->data = data ;
p->Lchild = NULL;
p->Rchild = NULL;
s[i] = p ;
if( i == 1 ) //编号为1的结点是树根
T = p ;
else//找新加入结点的双亲
{
j = i / 2; // j是i的双亲结点编号
if( i % 2 == 0 )
{
s[j]->Lchild = p;//左子树
//下面的输出是为了检验结点的位置是否跟预期相符。
#ifdef CHAR
printf( " %c 是 %c 的左子树\n", p->data, s[j]->data );
#else
printf( " %d 是 %d 的左子树\n", p->data, s[j]->data );
#endif
}
else
{
s[j]->Rchild = p;//右子树
#ifdef CHAR
printf( " %c 是 %c 的右子树\n", p->data, s[j]->data );
#else
printf( " %d 是 %d 的右子树\n", p->data, s[j]->data );
#endif
}
}
}
}
return( T );
}
int main()
{
BiTree *T = CreateBiTreeLevel( );
return 0;
}
4、运行结果