树
一种一对多的结构
有一个根节点和若干个分支节点构成的具有一对多关系的数据的集合
根节点:最顶层的节点
分支节点:有子节点的节点
叶子节点(终端节点):没有子节点的节点
树的深度:树的层数
树的广度(度):树中节点的度最大的值即为该树的度
节点的度:节点的子节点个数
二叉树
度为2的树是一个二叉树

满二叉树:在不增加层数的前提下,无法增加一个节点,这种二叉树是一个满二叉树

满二叉树:
第K层节点数:2^(K-1)
K层总节点数:2^K-1
完全二叉树:在满二叉树的基础上,按照从上至下,从左至右的方式增加若干个连续的节点。
满二叉树一定是一颗完全二叉树

二叉树的遍历
前序遍历:根,左子树,右子树 ABEFIDHMJ
中序遍历:左子树,根,右子树 EBFIAMHDJ
后序遍历:左子树,右子树,根 EIFBMHJDA
以上三种深度优先
层序遍历:从上至下,从左至右,逐层遍历 ABDEFHJIM 广度优先

前序遍历:ABC

前序 : ABC 后序:CBA

已知一个前序遍历和中序遍历结果,可以确定一颗唯一的二叉树
已知一个后序遍历和中序遍历结果,可以确定一颗唯一的二叉树
前序:ABEFIDHMJ
中序:EBFIAMHDJ


借助# , 不打印#
封装树节点结构体
数据,左子节点指针,右子节点指针
cpp
typedef char DataType;
typedef struct trnode
{
DataType data;
struct trnode *pl;
struct trnode *pr;
}TNode_t;
创建二叉树函数
二叉树先序序列,#代表空节点
idx 全局遍历下标
返回二叉树结点结构体指针的函数
调用malloc申请存放结点的堆内存,进行是否申请成功判断
递归创建左子节点,递归创建右子节点
cpp
DataType tree[] = {"ABE##F#I##DHM###J##"};
int idx = 0;
TNode_t*create_bin_tree()
{
DataType data = tree[idx++];//取下一个字符,下标后移
if('#' == data)
{
return NULL;//遇到#,表示空结点,返回NULL
}
TNode_t*pnode = malloc(sizeof(TNode_t));
if(NULL == pnode)
{
printf("malloc error\n");
return NULL;
}
pnode->data = data;
pnode->pl = create_bin_tree();
pnode->pr = create_bin_tree();
return pnode;
}
前序遍历输出函数
根,左子树,右子树
传入参数为根节点指针,进行判断传入的根节点是否为空节点,不为空,
打印输出根节点,递归打印输出左子节点,递归打印输出右子节点
cpp
void pre_order(TNode_t*proot)
{
if(NULL == proot)
{
return ;
}
printf("%C",proot->data);
pre_order(proot->pl);
pre_order(proot->pr);
}
中序遍历输出函数
左子节点,根,右子节点
传入参数为根节点指针,进行判断传入的左子节点是否为空,
递归打印输出左子节点,打印输出根节点,递归打印输出右子节点
cpp
void mid_order(TNode_t*proot)
{
if(NULL == proot)
{
return;
}
mid_order(proot->pl);
printf("%c",proot->data);
mid_order(proot->pr);
}
后序遍历输出函数
左子节点,右子节点,根节点
传入参数为根节点指针,进行判断传入的根节点是否为空
递归打印输出左子节点,递归打印输出右子节点,打印输出根节点
cpp
void pos_order(TNode_t*proot)
{
if(NULL == proot)
{
return;
}
pos_order(proot->pl);
pos_order(proot->pr);
printf("%c",proot->data);
}
计算二叉树总结点数函数
传入参数为树的根节点指针
根节点为空,直接退出
递归累加根节点+左子节点+右子节点

cpp
int get_tree_node_cnt(TNode_t*proot)
{
if(NULL == proot)
{
return 0;
}
return 1+get_tree_node_cnt(proot->pl)+get_tree_node_cnt(proot->pr);
}
销毁二叉树
传入参数为根节点指针,进行判断根节点是否为空
递归销毁左子节点,递归销毁右子节点,销毁根节点
释放指针内存空间后,将指针置空,避免成为野指针
cpp
void destory_tree(TNode_t*proot)
{
if(NULL == proot)
{
return;
}
destory_tree(proot->pl);
destory_tree(proot->pr);
free(proot);
proot = NULL;
}
层序遍历函数

借助队列
传入参数为根节点指针,创建队列(先进先出),定义局部变量,表示出队数据
根节点指针入队,以队列不为空为条件,开始循环
出队节点,打印输出节点指针指向内容,
若左、右子节点不为空,入队左、右子节点
队列为空,循环结束,销毁队列
cpp
void layer_node(TNode_t*proot)
{
Queue_t*pqueue = NULL;
Datatype_t outdata;
pqueue = create_link();
if(NULL == pqueue)
{
return ;
}
input_queue(pqueue, proot);
while(!is_empty_queue(pqueue))
{
output_queue(pqueue, &outdata);
printf("%c",outdata->data);
if(outdata->pl!= NULL)
{
input_queue(pqueue, outdata->pl);
}
if(outdata->pr!= NULL)
{
input_queue(pqueue, outdata->pr);
}
}
destory_queue(&pqueue);
return ;
}