本文内容基于《漫画算法 小灰的算法之旅》,魏梦舒著。
1. 树
树是n个节点的有限集。当n=0时,称为空树。在任意一个非空树中,有如下特点:
- 有且仅有一个特定的称为根的节点;
- 当n>1时,其余节点可分为m个互不相交的有限集,每一个集合本身又是一个树,并称为根的子树。
树的最大层级数,称为树的高度或深度。
2. 二叉树
树的每个节点最多有2个孩子节点。
2.1 满二叉树
一个二叉树的所有非叶子节点都存在左右孩子,并且所有叶子节点都在同一层级上。
2.2 完全二叉树
对一个有n个节点的二叉树,按层级顺序编号,则所有节点的编号为1到n。要求这个树所有节点和同样深度的满二叉树的编号为从1到n的节点位置相同。完全二叉树只需保证最后一个节点之前的节点都齐全即可。
3. 二叉树的应用
3.1 查找
二叉查找树在二叉树的基础上增加了以下几个条件:
- 如果左子树不为空,则左子树上所有节点的值均小于根节点的值;
- 如果右子树不为空,则右子树上所有节点的值均大于根节点的值;
- 左、右子树也都是二叉查找树。
对于一个节点分布相对均衡的二叉查找树来说,如果节点总数是n,那么搜索节点的时间复杂度都是O(logn),和树的深度是一样的。
3.2 维持相对顺序(插入)
二叉查找树的特性保证了二叉树的有序性,因此还有另外一个名字:二叉排序树。
插入的过程中,可能会出现需要二叉树进行自平衡,例如下图的情况:
二叉树的自平衡的方式有很多种,如红黑树、AVL树、树堆等。
4. 二叉树的遍历
- 深度优先遍历
- 前序遍历
- 中序遍历
- 后序遍历
- 广度优先遍历
- 层序遍历
public class TreeTest {
/**
* 二叉树节点
*/
private static class TreeNode {
int data;
TreeNode leftChild;
TreeNode rightChild;
public TreeNode(int data) {
this.data = data;
}
}
/**
* 构建二叉树
* 注意这里构建的顺序和前序遍历的顺序相同
* @param inputList
* @return
*/
public static TreeNode createBinaryTree(LinkedList<Integer> inputList) {
TreeNode node = null;
if (inputList == null || inputList.isEmpty()) {
return null;
}
Integer data = inputList.removeFirst();
if (data != null) {
node =