1、数组数据说明
数组中的数据是按照二叉树的层次存放的,位置上没有数据的放NULL.
比如:
int a[] = {5,1,4,NULL,NULL,3,6};
2、数组数据构建二叉树
2.1、构建节点
如上图,节点需要一个结构体指针成员指向左孩子
一个结构体指针成员指向右孩子
一个成员存储数据
typedef struct node
{
struct node *lchild; // 指向左孩子指针
int data; // 存储数据
struct node *rchild; // 指向右孩子指针
}NODE;
2.2、生成链表
1、获取数组中数据构造的二叉树的层次
每个节点最多有两颗子树的树称为 二叉树。
数组中的数据按照1生2,2生4......的规则构造二叉树
数组元素总个数 <= 2^0+2^1+2^2+......2^n = 2^(n+1)-1
所以,二叉树的层次 = 向下取整( log2(数组元素总个数) )
2、构造链表
按照上一步求出的层次,生成新节点放置数组中的数据。
由上图可以看出此二叉树和对应的一维数组中的索引值有以下关系:
1、左子树的索引值是父节点的索引值乘2。
2、右子树的索引值是父节点的索引值乘2加1。
注意:
为了方便使用索引是从1开始的,但是数组下标要从0开始。
已知索引求当前索引对应数据在二叉树的第几层: 向下取整( log2(索引) )即可。
思路:
节点地址 转换函数(数组,索引,长度)
{
获取二叉树的层次
获取当前索引 在第几层
如果索引对应数组数据 == NULL 或者 索引 > 长度
{
返回 NULL 结束
}
否则
{
创建节点
将索引对应的数组数据写入节点data中
如果 当前是最后一层节点
{
将节点的左右孩子设置为NULL
}
否则
{
// 添加下一级左右孩子
节点->lchild = 转换函数(数组,2*索引,长度);
节点->rchild = 转换函数(数组,2*索引+1,长度);
}
最后返回节点地址
}
}
代码:
// 根据数组生成链表并将头结点的地址返回
NODE *makeLink(int arr[],int idx,int size)
{
// 二叉树的层次
static int fNum;
fNum = bBinaryTreeFloor(size);
// 根据下标求当前节点在第几层 -- 对数
int nfloor = (int)floor(log2(idx));
// 如果数组元素值为NULL或者节点在数组中没有 左孩子或者右孩子了
if(arr[idx-1] == NULL || idx > size)
{
return NULL;
}
// 创建节点
NODE *p = (NODE *)malloc(sizeof(NODE));
// 添加节点数据
p->data = arr[idx-1];
if(nfloor == fNum - 1)
{
// 如果是最后一层的节点即叶子节点则左右孩子指针为NULL
p->lchild = NULL;
p->rchild = NULL;
}
else
{
// 继续向下添加左孩子
p->lchild = makeLink(arr,2*idx,size);
// 继续向下添加右孩子
p->rchild = makeLink(arr,2*idx+1,size);
}
// 将节点地址返回给它父亲的左右指针
return p;
}
3、遍历二叉树验证
二叉树的编译可以参考:二叉树遍历C语言实现
本例使用后序遍历进行检测构造的链表是否完好。
int main()
{
NODE *root = NULL;
// int a[] = {2,1,3};
int a[] = {5,1,4,NULL,NULL,3,6};
int len = sizeof(a) / sizeof(int);
root = makeLink(a,1,len);
postOrder(root);
return 0;
}