1866 字
9 分钟
树的知识总结

一、树的基本定义与术语#

1. 什么是树?#

是一种非线性的数据结构,它是由 n (n≥0) 个有限节点组成的一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,根在上,叶在下。

  • 空树:当 n=0 时,称为空树。
  • 非空树:在任意一棵非空树中,有且仅有一个特定的节点称为

2. 关键术语(结合下图理解)#

让我们通过一个例子来理解这些术语:

A (根节点)
/|\
B C D
/ \ \
E F G
/ \
H I
  • 节点:树中的每个元素,如图中的 A, B, C, …, I。
  • 根节点:没有父节点的节点,即树最顶层的节点。(A)
  • 父节点:一个节点的直接上层节点。如 B 是 E 和 F 的父节点。
  • 子节点:一个节点的直接下层节点。如 E 和 F 是 B 的子节点。
  • 兄弟节点:具有相同父节点的节点。如 B, C, D 互为兄弟节点;E 和 F 互为兄弟节点。
  • 叶节点/终端节点:没有子节点的节点。如图中的 C, F, H, I, G
  • 分支节点/非终端节点:不是叶节点的节点(即至少有一个子节点)。如图中的 A, B, D, E。
  • 节点的度:一个节点拥有的子节点个数。例如:
    • 节点 A 的度 = 3 (有B, C, D三个子节点)
    • 节点 B 的度 = 2 (有E, F两个子节点)
    • 节点 C 的度 = 0 (是叶节点)
  • 树的度:树内各节点的度的最大值。在上面的树中,节点的度最大为 3 (节点A),所以这棵树的度是 3。
  • 路径:从节点 n1nk 的路径是一个节点序列 n1, n2, ..., nk,其中对于 1 ≤ i < k,nin(i+1) 的父节点。路径的长度是所经过的边的数量
    • 例如,从 A 到 H 的路径是 A -> B -> E -> H,路径长度为 3。
  • 祖先与子孙:如果从根节点到节点 q 存在一条路径,且节点 p 在这条路径上,那么 pq祖先qp子孙
    • 例如,A, B, E 都是 H 的祖先;H, I 是 E 的子孙。

二、深度与高度(重点与易混点)#

这是两个非常容易混淆的概念,但它们有本质的区别。核心记忆点:深度是自上而下累加,高度是自下而上累加。

1. 节点的深度#

  • 定义:从根节点到该节点所经过的边的数量
  • 计算方法:从根节点开始(深度为0),每向下一层,深度加1。
  • 特点根节点的深度为0(或某些教材定义为1,但计算机科学中普遍使用0,面试时需确认)。一个节点的深度由其祖先节点决定。

在上面的例子中:

  • 节点 A 的深度 = 0 (根节点)
  • 节点 B 的深度 = 1
  • 节点 E 的深度 = 2
  • 节点 H 的深度 = 3

2. 节点的高度#

  • 定义:从该节点到其最远叶节点所经过的边的数量
  • 计算方法:从该节点开始,向下遍历到最远的叶节点,计算路径上的边数。
  • 特点所有叶节点的高度为0。一个节点的高度由其子孙节点决定。

在上面的例子中:

  • 节点 H 的高度 = 0 (叶节点)
  • 节点 E 的高度 = 1 (到 H 或 I)
  • 节点 B 的高度 = 2 (路径 B -> E -> H/I)
  • 节点 A 的高度 = 3 (路径 A -> B -> E -> H/I 或 A -> D -> G)

3. 树的深度/高度#

  • 定义树中所有节点的深度的最大值,也就是根节点的高度
  • 在上例中,树的深度/高度 = 3。

三、深度与高度的计算方法(递归与迭代)#

我们通常使用递归来定义和计算它们,因为树本身就是递归定义的。

递归定义#

  • **节点的高度 **height(node):
    • 如果 nodenull (空树或空子树),返回 -1。
    • 如果 node 是叶节点 (即 node.leftnode.right 都为 null),返回 0。
    • 否则,返回 1 + max(height(node.left), height(node.right))
    • 解释:节点的高度是其左右子树中较高的那个的高度再加1(加的1是连接自己和子节点的这条边)。
  • 节点的深度:
    • 在树的结构中,我们通常不会为每个节点单独计算深度,因为深度是从根节点开始传递的。通常是在遍历(如前序遍历)时,将当前深度作为参数传递下去。

代码示例(以计算节点高度为例)#

以下是一个简单的二叉树节点类和计算高度的方法:

class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def get_height(node):
"""
计算二叉树中某个节点的高度 (递归方法)
"""
# 1. 基准情况:如果节点为空,返回-1
if node is None:
return -1
# 2. 递归计算左子树和右子树的高度
left_height = get_height(node.left)
right_height = get_height(node.right)
# 3. 当前节点的高度是左右子树中较大的那个高度 + 1
return 1 + max(left_height, right_height)
# 构建示例树: A(B(E(H,I),F),C,D(G))
# 注意:这是一个多叉树,为了代码演示,我们构建一个类似的二叉树结构。
# A
# / \
# B C
# / \ \
# E F D
# / \ \
# H I G
root = TreeNode('A')
root.left = TreeNode('B')
root.right = TreeNode('C')
root.left.left = TreeNode('E')
root.left.right = TreeNode('F')
root.left.left.left = TreeNode('H')
root.left.left.right = TreeNode('I')
root.right.right = TreeNode('D')
root.right.right.right = TreeNode('G')
print(f"The height of the tree is: {get_height(root)}") # 输出: 3 (从A到H)
print(f"The height of node 'B' is: {get_height(root.left)}") # 输出: 2 (从B到H)
print(f"The height of node 'E' is: {get_height(root.left.left)}") # 输出: 1 (从E到H)

迭代方法(使用层次遍历计算树的高度)#

我们也可以使用队列进行广度优先搜索(BFS)来计算树的高度。

from collections import deque
def get_height_iterative(root):
"""
使用层次遍历(BFS)计算树的高度 (迭代方法)
"""
if root is None:
return -1
height = -1 # 初始化为-1,因为根节点所在层是第0层
queue = deque([root])
while queue:
level_size = len(queue)
# 处理当前层的所有节点
for _ in range(level_size):
node = queue.popleft()
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
# 每处理完一层,高度加1
height += 1
return height
print(f"The height of the tree (iterative) is: {get_height_iterative(root)}") # 输出: 3

总结与对比#

概念定义计算视角基准情况
节点的深度根节点到该节点的路径长度自上而下根节点的深度为0
节点的高度从该节点到最远叶节点的路径长度自下而上叶节点的高度为0,空节点高度为-1
树的高度/深度根节点的高度所有节点深度的最大值--

学习建议:

  1. 画图:对于任何树的问题,先在纸上画出来,手动标出每个节点的深度和高度。
  2. 理解递归:递归是解决树问题最自然、最强大的工具,务必掌握其思想。
  3. 分清视角:时刻记住深度是“我从根那里下来了多少步”,高度是“我的子孙中最远的那个离我多远”。

希望这份总结对你有帮助!树是数据结构中的一个宝库,打好基础后,学习二叉树、二叉搜索树、AVL树等都会轻松很多。如果你有任何疑问,随时可以再问我。


树的知识总结
https://94w.netlify.app/posts/树/
作者
94Whhh
发布于
2025-12-14
许可协议
CC BY-NC-SA 4.0