5.1 树的遍历
5.1.1 深度优先搜索(DFS)
题目:给定一棵树,使用深度优先搜索遍历这棵树。
解答:
class TreeNode:
def __init__(self, value):
self.value = value
self.children = []
def dfs(node):
print(node.value)
for child in node.children:
dfs(child)
# 示例
root = TreeNode(1)
root.children.append(TreeNode(2))
root.children.append(TreeNode(3))
root.children[0].children.append(TreeNode(4))
root.children[0].children.append(TreeNode(5))
root.children[1].children.append(TreeNode(6))
dfs(root)
解析:该代码定义了一个简单的树节点类 TreeNode,包含一个值和一个子节点列表。dfs 函数以递归方式遍历树的每个节点。
5.1.2 广度优先搜索(BFS)
题目:给定一棵树,使用广度优先搜索遍历这棵树。
解答:
from collections import deque
def bfs(root):
queue = deque([root])
while queue:
node = queue.popleft()
print(node.value)
for child in node.children:
queue.append(child)
# 示例
bfs(root)
解析:该代码使用一个队列来实现广度优先搜索。从根节点开始,依次将子节点加入队列,然后依次处理队列中的节点。
5.2 最小生成树
5.2.1 克鲁斯卡尔算法
题目:给定一个加权无向图,使用克鲁斯卡尔算法求最小生成树。
解答:
class UnionFind:
def __init__(self, vertices):
self.parent = {v: v for v in vertices}
self.rank = {v: 0 for v in vertices}
def find(self, v):
if self.parent[v] != v:
self.parent[v] = self.find(self.parent[v])
return self.parent[v]
def union(self, u, v):
root_u = self.find(u)
root_v = self.find(v)
if root_u != root_v:
if self.rank[root_u] > self.rank[root_v]:
self.parent[root_v] = root_u
elif self.rank[root_u] < self.rank[root_v]:
self.parent[root_u] = root_v
else:
self.parent[root_v] = root_u
self.rank[root_u] += 1
def kruskal(edges):
uf = UnionFind(set([edge[0] for edge in edges] + [edge[1] for edge in edges]))
mst = []
for edge in sorted(edges, key=lambda x: x[2]):
if uf.find(edge[0]) != uf.find(edge[1]):
mst.append(edge)
uf.union(edge[0], edge[1])
return mst
# 示例
edges = [(1, 2, 3), (2, 3, 1), (3, 4, 2), (1, 4, 4)]
print(kruskal(edges))
解析:该代码使用并查集实现克鲁斯卡尔算法。UnionFind 类用于管理节点的集合,kruskal 函数按照边的权重排序,并依次将不形成环的边加入最小生成树。
5.2.2 普里姆算法
题目:给定一个加权无向图,使用普里姆算法求最小生成树。
解答:
from heapq import heappop, heappush
def prim(edges, start):
mst = []
queue = [(0, start)]
visited = set([start])
while queue:
weight, node = heappop(queue)
mst.append((weight, node))
for edge in edges[node]:
if edge[1] not in visited:
heappush(queue, (edge[2], edge[1]))
visited.add(edge[1])
return mst
# 示例
print(prim(edges, 1))
解析:该代码使用优先队列实现普里姆算法。从指定节点开始,按照边的权重依次添加边到最小生成树。
5.3 欧拉图
5.3.1 欧拉图判定
题目:给定一个无向图,判断它是否是欧拉图。
解答:
def is_eulerian(graph):
odd_degree_nodes = [node for node in graph if len(graph[node]) % 2 != 0]
return len(odd_degree_nodes) == 0 or len(odd_degree_nodes) == 2
# 示例
graph = {1: [2, 3], 2: [1, 3, 4], 3: [1, 2], 4: [2]}
print(is_eulerian(graph))
解析:该代码检查图中奇数度节点个数。如果个数为0或2,则图是欧拉图。
5.4 图的着色
5.4.1 色数判定
题目:给定一个无向图,判断它是否可以着色,且每个相邻节点颜色不同。
解答:
def is_bipartite(graph):
colors = {node: None for node in graph}
def dfs(node, color):
if colors[node] is None:
colors[node] = color
elif colors[node] != color:
return False
for neighbor in graph[node]:
if not dfs(neighbor, 1 - color):
return False
return True
for node in graph:
if colors[node] is None:
if not dfs(node, 0):
return False
return True
# 示例
print(is_bipartite(graph))
解析:该代码使用深度优先搜索判断图是否是二分图。如果每个相邻节点颜色不同,则图可以着色。
5.5 有向图
5.5.1 有向图判定
题目:给定一个有向图,判断它是否是强连通图。
解答:
def is_strongly_connected(graph):
def dfs(node):
visited.add(node)
for neighbor in graph[node]:
if neighbor not in visited:
dfs(neighbor)
visited = set()
dfs(next(iter(graph)))
if len(visited) != len(graph):
return False
visited = set()
dfs(next(iter(graph)))
return len(visited) == len(graph)
# 示例
graph = {1: [2], 2: [3], 3: [1]}
print(is_strongly_connected(graph))
解析:该代码使用深度优先搜索判断有向图是否是强连通图。如果从任意节点开始,可以访问到所有其他节点,则图是强连通图。
