一、树基本特性
属性
- 树的度(degree of tree):是指树中节点最大度
- 高度(height)、深度(depth):指树的纵向最大层数,即纵向的最大高度
二、种类
二叉树
- 所有节点度小于等于2
- 区分左右子树,树不区分子树的顺序
- 二叉树可以没有任何节点,树至少有一个节点
二叉树中,第 i i i层的节点数最多为 2 i − 1 2^{i-1} 2i−1
二叉树深度为 k k k,节点总数最多为 2 k − 1 2^k-1 2k−1
叶节点有 n 0 n_0 n0个,度为2的节点有 n 2 n_2 n2个,则 n 0 = n 2 + 1 n_0=n_2+1 n0=n2+1
完全二叉树
从左到右、从上到下编号、有连续右兄弟的二叉树。
对n个节点的完全二叉树从1开始顺序编号。若顺序存储(数组),则对于下标为 i i i的节点:
其父节点下标为 ⌊ i / 2 ⌋ \lfloor i/2 \rfloor ⌊i/2⌋;若 i = 1 i=1 i=1, i i i是根节点。
左儿子下标为 2 i 2i 2i;若 2 i > n 2i>n 2i>n, i i i没有左儿子。
右儿子下标为 2 i + 1 2i+1 2i+1;若 2 i + 1 > n 2i+1>n 2i+1>n, i i i没有右儿子。
堆
最大堆(max heap)、最大树(max tree): 父节点的值不小于其所有儿子节点的值的完全二叉树
- 是完全二叉树
- 每一个子树,父节点都大于等于儿子节点。
最小堆、最小树定义同上,父节点的值最小
二叉查找树
- 左子树皆小于父节点,右子树皆大于父节点 的有序二叉树。
- 可以是空树。
- 任意两个节点的值不相等。
也叫二叉搜索树。
向二叉查找树插入节点时,会出现倾斜严重的树,最终导致查找效率为 O ( n ) O(n) O(n)。因此,在每进行插入、删除操作时都对二叉查找树做维护,保证每一次操作后的树都是平衡的,从而提出平衡二叉树(平衡二叉树,其实叫做平衡的二叉查找树)
平衡二叉树(AVL树)
左子树和右子树的高度之差的绝对值不超过1 的二叉查找树,叫做自平衡二叉查找树(Self-Balancing Binary Search Tree),简称平衡二叉树。
- 是一个二叉查找树,具有二叉查找树的性质。
- 左右子树高度差不超过1.
红黑树
红黑树,顾名思义就是节点为红色或者黑色的树。其本身是一个平衡的二叉查找树。
它具有如下性质:
- 根节点必须是黑色的
- 不能有连续两层都是红色节点
- 每个红色节点的两个子节点必须都是黑色的
- 任意节点到每个叶子节点路径上包含相同数量的黑色节点
- 每个叶节点是黑色的,NIL
这个性质的顺序很重要,1最重要,重要性依次往下。因为后面涉及到的插入等操作,都是根据以上顺序来确定的。
红黑树应用场景:
- JDK中TreeMap、TreeSet底层的实现
- Java8中HashMap底层
AVL树与红黑树的区别
- 两者都是二叉查找树的变种,都保证了平衡性。
- 但是AVL树是绝对平衡树,而红黑树追求大致的平衡。因而AVL树会比红黑树多大量的旋转操作,耗时更多。但是由于AVL树是绝对平衡的树,所以查询效率会更高。
所以,AVL树适合查询多而插入、删除操作较少的情况,红黑树适合插入、删除操作多而查询较少的情况。
三、二叉树的遍历(非递归)
二叉树表示
class TreeNode {
// 二叉树节点
int value = 0;
TreeNode left = null; // 左儿子
TreeNode right = null; // 右儿子
public TreeNode() {
}
public TreeNode(int value) {
this.value = value;}
}
先序遍历
// 先序遍历
public ArrayList<Integer> preOrder(TreeNode root) {
ArrayList<Integer> res = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<>();
TreeNode temp = root; // 临时节点
while (temp != null || stack.size() > 0)