工作中只要需要表示层级关系,就会碰到树结构。它是一种非线性结构,由一个根节点和若干互不相交的子树组成,每棵子树本身又是一棵树。理解树的关键在于递归:根节点没有前驱,其他节点有且只有一个父节点,但可以有多个孩子。
这种结构里有一些常用的叫法,对照下面这张图就很直观。

- 结点拥有的子树数量叫度,比如 A 的度是 6。
- 度为 0 的结点是叶结点,像 B、H、P 这种。
- 一个结点如果有子结点,它就是子结点的父结点(比如 A 是 B 的父结点);反过来 B 是 A 的子结点。
- 树中结点的最大层次是树的高度或深度,图中这棵树高度是 4。
二叉树
二叉树是树的度最大为 2 的特殊情况,也就是说每个结点最多有两个分叉。普通树的结构太灵活,工程里用得最多的其实就是二叉树。
它由根结点加上左子树和右子树组成——注意左右是有顺序的,不能颠倒,所以二叉树是一种有序树。

两种特殊的二叉树要记住:
- 满二叉树:每一层的结点数都达到最大值。如果层数为 K,结点总数就是 2K - 1。
- 完全二叉树:深度为 K 的二叉树,其结点与同深度满二叉树中编号从 1 到 n 的结点一一对应。满二叉树就是特殊的完全二叉树。

完全二叉树的编号是连续的,中间断了就不是完全二叉树。这个性质让它能用数组顺序存储:物理上是一个数组,逻辑上还是一棵树。非完全二叉树要是硬用数组,会浪费很多空间,所以后面我们会用链式结构来存。
二叉树还有几个常用性质:
- 第 i 层最多有 2(i-1) 个结点(根层数为 1)。
- 深度为 h 的二叉树最大结点数是 2h - 1。
- 如果叶结点个数是 n₀,度为 2 的结点个数是 n₂,那么 n₀ = n₂ + 1。
- 满二叉树的深度 h = log₂(n + 1)。
完全二叉树的下标关系(数组从 0 开始编号):
- 父亲下标 i,左孩子是 2i + 1,右孩子是 2i + 2。
- 孩子下标 i,父亲就是 (i - 1) / 2。
前提是这些下标对应的结点确实存在。
链式存储与节点定义
非完全二叉树如果强行用数组,空间利用率太低,所以需要链式存储。每个结点用一个结构体表示,包含数据域、左指针和右指针。为了方便换类型,用 typedef 重定义一下。
// BTNode.h
# once
BTDataType;
BTDataType data;
}BTNode;


