04_二叉树
文章目录
1、树形结构
2、生活中的树形结构
- 使用树形结构可以大大提高效率
- 树形结构是算法面试的重点
3、树的基本概念
-
节点、根节点、父节点、子节点、兄弟节点
-
一棵树可以没有任何节点,称为空树
-
一棵树可以只有一个节点,也就是只有根节点
-
子树、左子树、右子树
我们把下面的这个树的一部分结构拿出来讲解:
如图:51为5的左子树,52则为右子树
-
节点的度:子树的个数
拿上图的1节点来说,它有2,3,4,5,6一共5个子节点,所以1这个节点的度为5
-
树的度:所有节点度中的最大值
树的度就是所有节点度中的最大值,上图所示中,节点最多的为根节点,所以,这颗树的度即为5
-
叶子节点:度为0的节点
如上图中的:21,31,51,52,61,221,222,223
-
非叶子节点:度不为0的节点
-
层数(level):根节点在第1层,根节点的子节点在第2层,以此类推
-
节点的深度(depth):从根节点到当前节点的唯一路径上的节点总数
如上图所示:根节点1的深度即为1->2->22->221|222|223,
所以节点1的深度就为4
-
节点的高度(height):从当前节点到最远叶子节点的路径上的节点总数
如上图所示:根节点1的高度即为最远路径到它的路径上的节点总数,所以节点1的高度即为4
-
树的深度:所有节点深度中的最大值
-
树的高度:所有节点高度中的最大值
-
树的深度等于树的高度
4、有序树、无序树、森林
- 有序数
- 树种任意节点的子节点之间有顺序
- 无序树
- 树种任意节点的子节点之间没有顺序关系
- 也称为“自由树”
- 森林
- 由m(m>=n)颗互不相交的树组成的集合
5、二叉树(Binary Tree)
- 二叉树的特点
- 每个结点的度最大为2(最多拥有2颗子树)
- 左子树和右子树是有顺序的
- 即使某节点只有一颗子树,也要区分左右子树
- 二叉树是有序树
如下图所示都为二叉树:
5.1、二叉树的性质
-
非空二叉树的第i层,最多有2^(i-1)个节点(i>=1)
-
在高度为h的二叉树上最多有2^h-1个节点(h>=1)
-
对于任何一颗非空二叉树,如果叶子节点个数为n0,度为2的节点个数为n2,则有:n0=n2+1
- 假设度为1的节点个数为n1,那么二叉树的节点总数n=n0+n1+n2
- 二叉树的边数T=n1+2*n2=n-1=n0+n1+n2-1
- 因此n0=n2+1
5.2、真二叉树(Proper Binary Tree)
真二叉树:所有节点的度都要么为0,要么为2
如图所示即为真二叉树:
如下图所示不是真二叉树:
5.3、满二叉树(Full Binary Tree)
- 满二叉树:最后一层节点的度都为0,其他节点的度都为2
- 在同样高度的二叉树中,满二叉树的叶子节点数量最多,总节点数量最多
- 满二叉树一定是真二叉树,真二叉树不一定是满二叉树
5.4、完全二叉树(Complete Binary Tree)
- 完全二叉树:对节点从上至下,从左至右开始编号,其所有编号都能与相同高度的满二叉树中的编号对应
- 叶子节点只会出现最后2层,最后1层的叶子节点都靠左对齐
- 完全二叉树从根节点至倒数第二层是一棵满二叉树
- 满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树
5.4.1、完全二叉树的性质
- 度为1的节点只有左子树
- 度为1的节点要么是1个,要么是0个
- 同样节点数量的二叉树,完全二叉树的高度最小
解析:节点最少的情况,就是最底下的一层只有一个节点,最多节点的对应情况其实就是满二叉树
-
一棵有n个节点的完全二叉树(n>0),从上到下,从左到右对节点从1开始进行编号,对任意第i个节点
-
如果i = 1,它是根节点
-
如果i > 1,它的父节点编号为floor(i / 2)
-
如果2i <= n,它的左子节点编号为2i
-
如果2i > n,它无左子节点
-
如果2i + 1 <= n,它的右子节点编号为2i + 1
-
如果2i + 1 > n,它无右子节点
-
-
一棵有n个节点的完全二叉树(n>0),从上到下,从左到右对节点从0开始进行编号,对任意第i个节点
- 如果i = 0,它是根节点
- 如果i > 0,它的父节点编号为floor( (i - 1) / 2 )
- 如果2i + 1 <= n - 1,它的左子节点编号为2i + 1
- 如果2i + 1 > n - 1,它无左子节点
- 如果2i + 2 <= n - 1,它的右子节点编号为2i + 2
- 如果2i + 2 > n - 1,它无右子节点
5.5、二叉树的遍历
- 遍历是数据结构中的常见操作
- 把所有元素都访问一遍
- 线性数据结构的遍历比较简单
- 正序遍历
- 逆序遍历
- 根据节点访问顺序的不同,二叉树的常见遍历有四种
- 前序遍历(Preorder Traversal)
- 中序遍历(Inorder Traversal)
- 后序遍历(Postorder Traversal)
- 层序遍历(Level Order Traversal)
5.5.1、前序遍历(Preorder Traversal)
-
访问顺序
-
根节点、前序遍历左子树、前序遍历右子树
-
如下图:前序遍历的结果是7,4,2,1,3,5,9,2,11,10,12
先遍历左子树上的节点,然后再遍历根节点,然后再遍历右子树上的节点
-
我们用递归的方法可以解决前序遍历的问题,具体代码如下:
/**
* 前序遍历
*//
public void preorderTraversal(){
preorderTraversal(root);
}
//**
* 前