一、二叉树的基本性质
先介绍一下二叉树,二叉树是数据结构中一种特殊的树形结构,也就是每个节点最多有俩个子树,即二叉树中不存在度大于二的节点(度表示一个节点的子树个数),而且二叉树有左右之分,顺序不能颠倒。
二叉树又有俩种特殊的二叉树,即满二叉树和完全二叉树。
满二叉树:
若一棵树的层数为k,它总结点数是2^k-1,则这棵树就是满二叉树。
完全二叉树:
若一棵树的层数为k,它前k-1层的总结点数是2^(k-1)-1,第k层的结点按照从左往右的顺序排列,则这棵树就是完全二叉树。
性质一:在二叉树的第i层上,最多有2^(i-1)个结点。
二叉树有且只有一个根节点,每个节点最多有俩个子树,所以第一层为一个节点,第二层最多为俩个节点,第三层最多为四个节点,可以发现规律,第i层最多有2^(i+1)个节点。
性质二:深度为k的二叉树,最多有2^k-1个节点。
由性质一可知,第i层的子树最多有2^(i-1)个节点,则前i层的节点数最多为2^k-1
性质三:
对于任何一棵二叉树,如果叶子结点的数量为n0,度为2结点的数量为n2,则n0=n2+1;
总数n 叶子节点n0 求度1的节点数 n1 = n- n0-(n0-1) 度2节点n2 = n0-1
性质四:具有n个结点的完全二叉树的高度为(log2n)+1
性质五:
有一个n个结点的完全二叉树,结点按照从上到下从左到右的顺序排序为1~n。
1、i > 1时,i/2就是它的双亲结点。
2、i*2是i的左子树,当i*2>n时,则i没有左子树。
3、2*i+1是i的右子树,2*i+1>n时,则i没有右子树。
二、二叉树的基本遍历
1、前序遍历:
1、判断二叉树是否为空,若二叉树为空,则不操作。
2、访问根结点
3、前序遍历左子树
4、前序遍历右子树
以此图为例,则前序遍历为:A B D G E H I C FJ
二叉树的遍历都需要用到递归的思想,为了方便实现,定义了一个字符串为二叉树的输入
“ABCDE#FG#HI##J”,‘#’号表示为当前位置没有子树。
定义一个顺序二叉树结构
// 顺序二叉树结构
typedef struct BinTree
{
TREE_TYPR* ptr;
size_t cap;
}BinTree;
接下来构建一个二叉树
// 构建二叉树
// 根据提供的完全二叉树层序遍历的结果,来构建一个堆内存中的二叉树
BinTree* create_tree(TREE_TYPR* arr,size_t len)
{
BinTree* tree = malloc(sizeof(BinTree));
tree->ptr = malloc(sizeof(TREE_TYPR)*len);
memcpy(tree->ptr,arr,sizeof(TREE_TYPR)*len);
tree->cap = len;
return tree;
}
实现前序遍历函数,需要用到递归的思想。
void _dlr_show(BinTree* tree,size_t index)
{
if(index>tree->cap || tree->ptr[index-1] == ‘#’)
return;
// 访问根节点
printf(“%c”,tree->ptr[index-1]);
// 对左子树前序遍历
_dlr_show(tree,2*index);
// 对右子树前序遍历
_dlr_show(tree,2*index+1);
}
void dlr_show(BinTree* tree)
{
_dlr_show(tree,1);
printf("\n");
}
2、中序遍历:
1、判断二叉树是否为空,若二叉树为空,则不操作。
2、中序遍历左子树
3、访问根结点
4、中序遍历右子树
中序遍历为 G D B H E I A C J F
void _ldr_show(BinTree* tree,size_t index)
{
if(index>tree->cap || tree->ptr[index-1] == '#')
return;
_ldr_show(tree,2*index);
printf("%c ",tree->ptr[index-1]);
_ldr_show(tree,2*index+1);
}
void ldr_show(BinTree* tree)
{
_ldr_show(tree,1);
printf("\n");
}
3、后序遍历:
1、判断二叉树是否为空,若二叉树为空,则不操作。
2、后序遍历左子树
3、后序遍历右子树
4、访问根结点
后续遍历为G D H I E B J F C A
void _lrd_show(BinTree* tree,size_t index)
{
if(index>tree->cap || tree->ptr[index-1] == '#')
return;
_lrd_show(tree,index*2);
_lrd_show(tree,2*index+1);
printf("%c ",tree->ptr[index-1]);
}
void lrd_show(BinTree* tree)
{
_lrd_show(tree,1);
printf("\n");
}