摘要
二叉树是树结构中最基础,也是最重要的结构。由二叉树衍生出多种不同类型的二叉树,当学习完二叉树的不同衍生结构后,会发现,都不能逃离二叉树的定义和特定。
树结构
生活中会遇到很多树形结构的场景,比如公司的组织架构、文件目录等等。使用树形结构是出于可以提高效率的目的。
基本概念
树有节点、根节点、父节点、子节点、兄弟节点这几个关键词。树可以没有一个节点,称为空树,也可以只有一个节点,即只有根节点。树也可以分为子树、左子树、右子树。
在树的结构中,有以下几个:
- 节点的度:子树的个数
- 树的度:所有节点度中的最大值
- 叶子节点:度为 9 的节点
- 非叶子节点:度不为 0 的节点
- 层数:根节点在第 0 层,根节点的子节点在第 2 层,以此类推,直到最后
- 节点的深度:从根节点到当前节点的唯一路径上的节点总数
- 节点的高度:从当前节点到最远叶子节点的路径上的节点总数
- 树的深度:所有节点深度中的最大值
- 树的高度:所有节点高度中的最大值
- 树的深度等于树的高度
树的类型
树分为有序树、无序树和森林。有序树中任意节点的子节点之间有顺序关系,无序树中任意节点的子节点之间没有顺序关系,森林由多颗互不相交的树组成的集合。
二叉树(Binary Tree)
二叉树是每个节点的度最大为 2(最多拥有 2 棵子树)的树,二叉树的左右子树有顺序。即使某一个节点只有一颗子树,也需要区分左右子树。
性质
二叉树总共有以下几个特点:
-
非空二叉树的第 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
二叉树的类型
- 真二叉树:所有节点的度要么为 0,要么为 2
- 满二叉树:所有节点的度都要么为 0,要么为 2。且所有的叶子节点都在最后一层
- 完全二叉树:叶子节点只会出现最后 2 层,且最后 1 层的叶子节点都靠左对齐
由上总结出,满二叉树一定是真二叉树,但是真二叉树不一定是满二叉树
实现
根据二叉树的特点,可以总结出每个节点有父节点、左子节点、右子节点,还有自身节点的元素。看左右子节点是否为空来判断该节点是叶子节点还是度为 2 的节点,代码如下:
static class Node<E> {
// 父节点
Node<E> parent;
// 左子节点
Node<E> left;
// 右子节点
Node<E> right;
// 元素
E element;
public Node(E element, Node<E> parent) {
this.element = element;
this.parent = parent;
}
/**
* 是否是叶子节点
*
* 通过判断是否 left 和 right 是否都为 null
*
* @return
*/
public Boolean isLeaf() {
return left == null && right == null;
}
/**
* 是否是度为 2 的节点
* @return
*/
public Boolean isHaveTowChildren() {
return left != null && right != null;
}
}