注:你的关注,点赞,评论让我不停更新
1. 树的基本概念与表示
概念
树是一种无向无环的连通图,由节点和边组成。其中有一个特殊节点被称为根节点,除根节点外,每个节点都有一个父节点。节点到根节点的路径上经过的节点数量称为该节点的深度,树中节点的最大深度就是树的高度。
表示方法
在 Python 中,常用邻接表来表示树。例如:
# 假设有 5 个节点的树,节点编号从 0 到 4
n = 5
# 初始化邻接表
tree = [[] for _ in range(n)]
# 添加边 (0, 1)
tree[0].append(1)
tree[1].append(0)
# 添加边 (0, 2)
tree[0].append(2)
tree[2].append(0)
# 添加边 (1, 3)
tree[1].append(3)
tree[3].append(1)
# 添加边 (1, 4)
tree[1].append(4)
tree[4].append(1)
2. 树的遍历
深度优先搜索(DFS)
-
原理:从根节点开始,沿着一条路径尽可能深地访问节点,直到无法继续,然后回溯到上一个节点,继续探索其他路径。
-
应用场景:计算树的深度、路径和、子树节点数量等。
-
示例代码:
# 计算树的深度
def dfs(node, parent, tree, depth):
max_depth = depth
for child in tree[node]:
if child != parent:
max_depth = max(max_depth, dfs(child, node, tree, depth + 1))
return max_depth
# 调用示例
root = 0
tree_depth = dfs(root, -1, tree, 0)
print("树的深度为:", tree_depth)
广度优先搜索(BFS)
-
原理:从根节点开始,逐层地访问节点,先访问距离根节点近的节点。
-
应用场景:求树的最短路径、层次遍历等。
-
示例代码:
from collections import deque
# 树的层次遍历
def bfs(root, tree):
queue = deque([root])
visited = [False] * len(tree)
visited[root] = True
result = []
while queue:
node = queue.popleft()
result.append(node)
for child in tree[node]:
if not visited[child]:
queue.append(child)
visited[child] = True
return result
# 调用示例
level_order = bfs(root, tree)
print("树的层次遍历结果为:", level_order)
3. 最近公共祖先(LCA)
概念
在树中,对于两个节点 u
和 v
,它们的最近公共祖先是指距离它们最近的共同祖先节点。
应用场景
-
计算树上两点之间的距离:
dist(u, v) = dist(u, root) + dist(v, root) - 2 * dist(lca(u, v), root)
。 -
处理树上的路径查询问题。
示例代码(简单的暴力法)
# 查找节点的祖先节点
def find_ancestors(node, parent, tree, ancestors):
ancestors.append(node)
for child in tree[node]:
if child != parent:
find_ancestors(child, node, tree, ancestors)
# 查找最近公共祖先
def lca(u, v, tree):
ancestors_u = []
find_ancestors(u, -1, tree, ancestors_u)
ancestors_v = []
find_ancestors(v, -1, tree, ancestors_v)
for node in ancestors_u:
if node in ancestors_v:
return node
# 调用示例
u = 3
v = 4
lca_node = lca(u, v, tree)
print(f"{u} 和 {v} 的最近公共祖先是:", lca_node)
4. 树的直径
概念
树的直径是指树中任意两个节点之间的最长路径的长度。
应用场景
-
求树中最远的两个节点的距离,例如在一些地图问题中,求两个地点之间的最长距离。
示例代码
# 第一次 DFS,找到距离起始节点最远的节点
def dfs1(node, parent, tree, distance):
max_dist = 0
farthest_node = node
for child in tree[node]:
if child != parent:
dist, far = dfs1(child, node, tree, distance + 1)
if dist > max_dist:
max_dist = dist
farthest_node = far
return max_dist + 1, farthest_node
# 第二次 DFS,计算树的直径
def tree_diameter(root, tree):
_, farthest = dfs1(root, -1, tree, 0)
diameter, _ = dfs1(farthest, -1, tree, 0)
return diameter - 1
# 调用示例
diameter = tree_diameter(root, tree)
print("树的直径为:", diameter)
5. 树的重心
概念
树的重心是指树中的一个节点,当把这个节点删除后,剩余的各个子树中节点数量的最大值最小。
应用场景
-
优化树的分治算法,选择重心作为分割点可以使子问题的规模更加均衡。
示例代码
# 计算树的重心
def find_centroid(node, parent, tree, n):
global centroid, min_max_subtree
size = 1
max_subtree = 0
for child in tree[node]:
if child != parent:
child_size = find_centroid(child, node, tree, n)
size += child_size
max_subtree = max(max_subtree, child_size)
max_subtree = max(max_subtree, n - size)
if max_subtree < min_max_subtree:
min_max_subtree = max_subtree
centroid = node
return size
# 调用示例
n = len(tree)
centroid = -1
min_max_subtree = float('inf')
find_centroid(root, -1, tree, n)
print("树的重心为:", centroid)
这些基础的树上问题在蓝桥杯的题目中经常出现,你需要熟练掌握它们的原理和实现方法,并且多做相关的练习题来提高解题能力。