手绘图手撕数据结构与算法系列目录:
手绘图系列 01 | 链表到底是什么?
手绘图系列 02 | 让人害怕的栈溢出
手绘图系列 03 | 排队?还是不排队?
到目前为止,我们主要介绍了一些线性的数据结构,如链表、队列、栈。在这些结构中,数据是有序的,而且顺序很重要。
今天我们要跳出这个框框,进入一个更加“有挑战性”的领域——非线性数据结构。我们将从使用频率最高的”树“开始!
记住!树是一种非常重要的非线性数据结构。
与树相关的术语
现实生活中,无论是橡树、枫树还是银杏树,都是从坚实的根部开始生长的。同样的,在树这种数据结构中,会有一个根节点(非空树),在根节点之上再衍生出多个其它节点。
当我们讨论树时,有几个关键术语你需要了解:
节点(Node):
树中的每个元素称为一个节点,每个节点可以包含一个值或者其他相关信息。边(Edge):
树中连接两个节点的线称为边。表示父节点与子节点之间的关系。根节点(Root Node):
树的最顶层节点,称为根节点,它没有父节点,是树的入口。叶子节点(Leaf Node):
没有子节点的节点称为叶子节点,也叫终端节点。父节点(Parent Node):
一个节点的上一级节点称为其父节点。子节点(Child Node):
一个节点下面连接的节点称为其子节点。兄弟节点(Sibling Node):
拥有同一个父节点的节点称为兄弟节点。节点深度(Depth):
从根节点到该节点所经过的边的数量。节点高度(Height):
从距离该节点最远的叶子节点到该节点所经过的边的数量。子树(Subtree):
由树中任意一个节点及其所有子孙节点组成的集合称为子树。节点的度(Degree):
一个节点其子节点的个数称为这个节点的度。树的度(Degree):
树中所有节点的最大度数称为树的度。
结合上图,不难理解这些概念,对于比较重要的概念,后面会详细介绍。
树的基本性质
在树(Tree)结构中,无论树外观如何,有多少个节点,都有一些普遍的定理和性质。
让我们看看下面这棵树。
它总共有 10 个节点(包括根节点),9 条边,我们看到节点个数比边的个数多1,事实上,无论树的节点数量多少,这个关系都是成立的:如果一棵树有 n 个节点,那么它一定有 n-1 条边。
这里还有一个有趣的事实:树中实际上包含着树!一棵树通常由较小的树组成,我们称之为子树。这意味着树是一种递归的数据结构,理解这一点非常重要,这对我们编写遍历或搜索树的算法非常有帮助。
树有多高
大多数情况下,我们最关注树的两个属性是节点的深度和节点的高度。
节点的高度(Height):
从距离该节点最远的叶子节点到该节点所经过的边的数量。叶子节点高度为0。节点的深度(Depth):
从根节点到当前节点路径上的边的数量。根节点的深度为 0。
理解节点深度的一个简单方法是问自己:这个节点距离树的根有多远?例如,在下图中,粉色节点的深度为 2,因为从粉色节点到根节点的路径恰好有 2 条边。而另一个紫色节点的深度为 3,因为从紫色节点到根节点的路径上恰好有 3 条边。
理解了节点深度之后,节点高度就相对容易了。同样你可以这样问自己:这个节点距离最远的叶子节点有多远?在示例中,橙色节点的高度为 3,因为其离最远的叶子节点(实际上有三个叶子节点离它最远!)需要 3 条边链接。
理解了节点的深度和节点的高度,进而引发出另外两个概念:树的高度和树的深度。
树的高度:
树的高度等于根节点的高度,等于最远叶子节点的深度。树的深度:
树的深度等于树的高度。
深度和高度这两个概念之所以如此重要,是因为通过它们可以告知我们一棵树到底是什么形状,一个简单的例子就是平衡树与非平衡树:每个节点的子树高度差不超过1则认为该树是平衡树。否则是非非平衡树。
树的应用
为了真正理解树这种数据结构的强大之处,我们必须从其应用的角度来看待它们。
一个简单的例子计算机上的文件系统!这实际上就是一个树形数据结构:有一个根目录,然后下面挂着许多子目录和文件。子目录相当于非叶子节点,因为它们还可以包含更多子目录或文件,而文件则相当于叶子节点,因为它们没有子节点。
下一篇文章将和大家深入探讨一种特别重要的树——二叉搜索树 !