Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

复习

  • 单向链表:节点用指针相连
  • 递归:函数调用自身来解决问题
  • 集合与映射:建立在哈希表之上的抽象

TL;DR

  • 树用父子关系表示层次结构
  • 每个节点最多有一个父节点,根没有父节点
  • 树天然适合用递归来处理
  • 层次结构在现实中随处可见

正文

  前面那些结构都是“一条线”:数组是一排,链表是一串,队列是一队。可现实里很多数据是有层次的:文件夹套文件夹、公司里有上下级、网页里有嵌套标签。要表示这种层次,就需要(tree)。

上下级关系

  树由一个个节点(node)组成,节点之间有“父子”关系:

  • (root):最顶层那个节点,没有父节点
  • 父节点 / 子节点:一个节点可以有多个子节点,但只有一个父节点
  • 叶子(leaf):没有子节点的节点

  从根出发到某个节点,经过的层数,叫它的深度;从某个节点往下到最远叶子的层数,叫它的高度。整棵树只有一个根,不会绕回来(没有环)。

  想想你的文件系统:根目录下有若干目录,每个目录里又有子目录和文件——这正是一棵树。

为什么树适合递归

  树有一个很关键的性质:去掉根之后,剩下的每一棵子树,本身又是一棵树。

  这种“自己包含更小的自己”的结构,和递归简直是天生一对。处理一棵树,往往可以写成:

  • 先处理根
  • 再分别递归地处理每一棵子树

  后面要讲的遍历、查找,几乎都会用到这个套路。结构是递归的,解法自然也是递归的。

和链表的区别

  值得对比一下:链表的每个节点,只有一个“后继”;而树的节点可以有好几个“后继”(子节点)。正是“一个变多个”,让树能表达层次,而不是一条直线。

  最常用、也最容易处理的一种树,是每个节点最多两个孩子的树——二叉树。下一章就从它开始。

思考题 1

  树和链表在“连接方式”上有什么不同?

思考题 2

  为什么树特别适合用递归来处理?

小结

知识点

  • 树用父子关系表达层次结构
  • 有根、父、子、叶等基本概念
  • 每个节点最多一个父节点,且无环
  • 子树本身也是树,适合递归处理

参考资料

  1. Wikipedia(zh):树 (数据结构):由节点和父子关系构成的层次结构
  2. Wikipedia(zh):递归:处理递归结构的自然方式

思考题答案(仅供参考)

思考题 1

  链表的每个节点只有一个后继,所以整体排成一条线;树的每个节点可以有多个子节点,因此能分出层次和分支。正是“一个变多个”,让树能表达层次结构。

思考题 2

  因为树本身是递归定义的:去掉根后,剩下的每个子树又是一棵树。处理树时,可以“处理根,再递归处理各子树”,这与树的定义一一对应,代码也就自然、简洁。

协议

  本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

封面图

设计师 | 南国微雪