从家谱和文件夹说起——认识节点、父子关系、深度与高度,为后面的存储和遍历打好地基。
你有没有留意过,家里的家谱和电脑里的文件夹,其实长得很像?家谱里,爷爷下面分出爸爸和叔叔,爸爸和叔叔下面又各自分出你和堂兄弟;文件夹也是一样,一个文件夹下面能装好几个子文件夹,子文件夹下面还能再装子文件夹。这种"一个东西能往下分出好几个,一层一层展开,绝不会转个圈又绕回去"的结构,在计算机里就叫树。
之所以叫"树",是因为倒过来看,它还真有点像一棵大树:最上面是树根,往下渐渐分叉出树枝,最后长出一片片树叶。只不过我们画图的时候习惯把"根"画在最上面,"叶子"画在最下面——这个习惯要提前说一声,免得和现实里的树反着看,反而觉得别扭。
C:\ 是根目录,下面有 Users、Program Files 等文件夹,Users 下面又有具体的用户文件夹……一层套一层,永远不会有一个文件夹同时是另一个文件夹的"孙子"又是它的"祖先"。下面用一棵具体的树,把树相关的术语一次性讲清楚。这棵树在接下来两节(存储、遍历)里还会反复用到,建议先记住它的样子:
1 是根节点(没有父节点,整棵树从它开始);2 是 1 的子节点,1 是 2 的父节点;2 和 3 互为兄弟节点(同一个父节点);4、5、6 都没有子节点,叫叶子节点。以 2 为根往下看(2、4、5),单独也构成一棵完整的树,叫 1 的子树。1 走到 4,路径是 1→2→4,经过了 2 条边。这个"经过了几条边"的数字,就是下一节要讲的深度。深度和高度这两个词看着像近义词,但方向完全相反,是初学者最容易搞混的地方:
| 概念 | 怎么数 | 方向 |
|---|---|---|
| 深度(depth) | 从根节点数到这个节点,经过几条边 | 自上而下 |
| 高度(height) | 从这个节点数到它最深的那个叶子,经过几条边 | 自下而上 |
4 的深度是 2(从根 1 走过 1→2→4 共 2 条边)。节点 2 的高度是 1(从 2 到它最深的叶子 4 或 5,只隔 1 条边)。整棵树的高度,通常就说成"根节点的高度"——这里是 2。叶子节点的高度永远是 0(自己就是最深的叶子,不用再往下走)。树的每个节点可以有任意多个子节点(比如文件夹可以有很多子文件夹)。但学算法时最常遇到、也最重要的一种树,是二叉树——规定每个节点最多只能有两个子节点,分别叫左子节点和右子节点(哪怕只有一个子节点,也要分清楚它是"左"还是"右",这一点在下一节讲存储方式时很关键)。
上面例子里的树,每个节点的子节点数都不超过 2 个,所以它本身就是一棵二叉树:节点 1 的左子节点是 2、右子节点是 3;节点 3 只有左子节点 6、没有右子节点。
4、5、6,从左到右紧挨着排列,没有跳过任何位置。把本节内容汇总成几条最容易踩坑的规则:
left 还是 right 指针,混淆会导致存储和遍历都出错。