由于二叉树的基础思想还是比较简单的,所以这里不做过多的讲解,只需要记住一个二叉树每个节点的度(子结点数)至多为2,至少为0。满二叉树就是除叶结点外,每个结点的度都为2;完全二叉树就是与同深度的满二叉树的节点顺序是一致的就是完全二叉树。这里直接上图,对于二叉树的遍历方式,这里不做讲解,后面会有单独文章进行说明。
1、满二叉树
2、完全二叉树
其实二叉树的存储结构和上一篇文章讲解的树的存储结构思想是大同小异的,只不过二叉树至多有两个子结点而已,所以他的存储结构也就相对于好设计很多,具体看代码就可以了,每行代码的注释已经很清晰。
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
typedef int Status;
typedef char ElemType;
//定义一个链队列的结点存储结构
typedef struct QNode
{
ElemType data;
QNode *next;
}QNode,*QueueLink;
//定义一个链队列的存储结构, 用于存储即将构造二叉树的数据
typedef struct
{
QueueLink front;
QueueLink rear;
int length;
}Queue;
//定义二叉树存储结构
typedef struct BNode
{
ElemType data; //数据域
struct BNode *leftChild, *rightChild; //指针域,分别定义指向左子结点和右子节点
}BNode, *Tree;
//对队列进行初始化
void Init(Queue *q)
{
QueueLink link = (QueueLink)malloc(sizeof(QNode));
link -> next = NULL;
q -> front = link;
q -> rear = link;
q -> length = 0;
}
//批量添加元素
void BatchIn(Queue *q, ElemType data[], int len)
{
for(int i = 0; i < len; i++)
{
QueueLink link = (QueueLink)malloc(sizeof(QNode));
link -> next = NULL;
q -> rear -> data = data[i];
q -> rear -> next = link;
q -> rear = link;
q -> length++;
}
}
//出队
ElemType Out(Queue *q)
{
if(q -> front != q -> rear)
{
QueueLink link;
link = q -> front;
ElemType data = link -> data;
q -> front = link -> next;
free(link);
q -> length--;
return data;
}
else
{
return NULL;
}
}
//创建二叉树,采取正序遍历方式
void CreateBTree(Tree *t, Queue *q)
{
ElemType data = Out(q);
if(data != NULL)
{
if(data == '#') //如果为'#'号,说明这个树节点不存在, 赋值为空
{
(*t) = NULL;
}
else
{
(*t) = (Tree)malloc(sizeof(BNode));
(*t) -> data = data;
CreateBTree(&((*t) -> leftChild), q);
CreateBTree(&((*t) -> rightChild), q);
}
}
else
{
(*t) = NULL; //这里是为了判断当'#'号数量不匹配的时候,自动赋值为空
}
}
//读取二叉树,正序遍历
void ReadTree(Tree t)
{
if(t == NULL)
{
return;
}
printf("%c\n", t -> data);
ReadTree(t -> leftChild);
ReadTree(t -> rightChild);
}
int main(void)
{
ElemType e[] = {'A','B','#', 'D', '#', '#', 'C', '#', '#'};
int len = sizeof(e)/sizeof(e[0]);
Queue q;
Tree t;
Init(&q);
BatchIn(&q, e, len);
CreateBTree(&t, &q);
ReadTree(t);
return 0;
}