链式二叉树总结(简略版)
树的相关概念
- 节点的度:一个节点含有的子树的个数称为该节点的度。
- 树的度:一棵树中,最大的节点的度称为树的度。
- 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推。
- 树的高度或深度:树中节点的最大层次。
- 双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点。
- 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点。
- 兄弟节点:具有相同父节点的节点互称为兄弟节点。(亲兄弟才能叫做兄弟节点,表兄、堂兄不行)
- 堂兄弟节点:双亲在同一层的节点互为堂兄弟。
- 节点的祖先:从根到该节点所经分支上的所有节点。
- 森林:由m(m>0)棵互不相交的树的集合称为森林。
二叉树概念及结构
一棵二叉树是节点的一个有限集合,每一棵树都是由根、左子树和右子树构成。二叉树不存在度大于2的结点。
两种特殊的二叉树
满二叉树:
一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为k,且结点总数是2^k-1 ,则它就是满二叉树。
完全二叉树
如果一个二叉树的层数为k,前面k-1层是满二叉树,最后一层(第k层)从左向右是连续的。要注意的是满二叉树是一种特殊的完全二叉树。
二叉树的有关性质
- 对任何一棵二叉树, 如果度为0其叶结点个数为N0 , 度为2的分支结点个数为N2 ,则有N0=N2+1。
- 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是2^h-1。
- 若规定根节点的层数为1,具有N个结点的满二叉树的深度,h=㏒₂(N+1)。由N=2^h-1来的。
二叉树的遍历
遍历下面的二叉树
前中后序遍历用递归。
层序用队列实现,上级出下级进的思想。
前序遍历(根 左子树 右子树)
核心代码
//前序遍历
void PreOrder(BT* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%d ", root->data);
PreOrder(root->left);
PreOrder(root->right);
}
中序遍历(左子树 根 右子树)
核心代码
//中序遍历
void InOrder(BT* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
InOrder(root->left);
printf("%d ", root->data);
InOrder(root->right);
}
后序遍历(左子树 右子树 根)
核心代码
//后序遍历
void PostOrder(BT* root)//6
{
if (root == NULL)
{
printf("NULL ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%d ", root->data);
}
层序遍历 (按顺序一层一层遍历)
用队列来做,先Push值为1的节点进队列,然后这个节点Pop出去,再Push这个节点的左节点(值为2)和右节点(值为4)。再Pop出值为2的节点,Push进值为2的节点的左右子节点,以此类推。
核心代码
计算二叉树节点的个数
思路
1.节点的个数 = 左子树节点的个数+右子树节点的个数 + 1(自己)。
2.遍历二叉树,不为NULL就++
代码1
//求数的节点的个数
int Size(BT* root)//root为根节点
{
if (root == NULL)
{
return 0;
}
//节点的个数为=左子树节点的个数+右子树节点的个数+1
int leftnum = Size(root->left);
int rightnum = Size(root->right);
return leftnum + rightnum + 1;
}
代码2
int size = 0;//全局变量
void Size(BT* root)
{
//遍历二叉树,没有遇到叶子就++
if (root == NULL)
{
return;
}
size++;
Size(root->left);
Size(root->right);
}
求二叉树的高度
思路
树的高度 = 左子树的高度和右子树的高度中较大的那个 + 1(自己)。
代码
//求二叉树的高度(深度)
int Height(BT* root)
{
//每一棵树的高度=左子树和右子树的较大的高度+1
if (root == NULL)
{
return 0;
}
else
{
int LeftNum = Height(root->left);
int RightNum = Height(root->right);
if (LeftNum > RightNum)
{
return LeftNum + 1;
}
else
{
return RightNum + 1;
}
}
}
求第k层节点的个数
思路
求第k层节点的个数=左子树的第k-1层节点的个数+右子树的第k-1层节点的个数
这样写看起开不错,实际上很挫:查一次遍历一遍,加一次在重复遍历一遍。解决办法就是把第一次遍历的数据记录下来。
代码
//求第k层节点的个数
int Level(BT* root, int k)
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
//用递归,就找相同的子问题
//第k层=找左子树和右子树的第k-1层
int LeftNum = Level(root->left, k - 1);
int RightNum = Level(root->right, k - 1);
return LeftNum + RightNum;
}
找值为x的节点并返回其地址
思路
用递归,找相同的问题:根的值是不是x,是就返回其地址,不是就找根的左节点和右节点。
代码
//查找节点为x的节点,若找到了就返回该节点的地址,否则返回空
BT* Find(BT*root, int x)
{
if (root == NULL)
return NULL;
if (root->data == x)
return root;
BT* lret = Find(root->left, x);
if (lret)
return lret;
BT* rret = Find(root->right, x);
if (rret)
return rret;
return NULL;
}
举例1:假设x=5.
举例2:假设x=8