
在处理复杂数据结构时,我们经常会遇到将字典视为图(graph)进行遍历的需求。设想我们有一个字典 my_dict,其中键代表节点,值代表其直接邻居节点。我们被赋予一个起始节点列表 source_list 和一个目标节点列表 target_list。任务是:从 source_list 中的每个节点开始,逐层(或称逐迭代)地遍历 my_dict,提取当前层级中与遍历路径相关的键值对,并将它们组织成一个结果字典,其中键是层级编号。遍历路径应在遇到 target_list 中的任何节点时停止。
例如,给定以下数据:
source_list = ['a', 'b']
target_list = ['x', 'y', 'z']
my_dict = {
'a': ['e'],
'b': ['f', 'd'],
'e': ['g'],
'f': ['t', 'h'],
'd': ['x'],
'g': ['x'],
't': ['y'],
'h': ['z']
}我们期望得到如下结果,其中键 0、1、2 代表遍历的层级:
{0: {'a': ['e'], 'b': ['f', 'd']},
1: {'e': ['g'], 'f': ['t', 'h'], 'd': ['x']},
2: {'g': ['x'], 't': ['y'], 'h': ['z']}}这种按层级提取数据的需求,正是广度优先搜索 (BFS) 算法的典型应用场景。
广度优先搜索是一种用于遍历或搜索树或图的算法。它从图的根节点(或任意给定节点)开始,首先探索所有邻近的节点,然后是下一层级的邻近节点,依此类推。这使得 BFS 非常适合解决需要“最短路径”或“按层级”遍历的问题。
立即学习“Python免费学习笔记(深入)”;
在 Python 中,collections 模块中的 deque(双端队列)是实现 BFS 队列的理想选择,因为它支持高效的从两端添加和移除元素操作。
以下是一个基于标准 BFS 算法的解决方案,它能够正确地按层级提取所需数据。
from collections import deque
def bfs_extract_levels(source, target, graph):
"""
使用广度优先搜索从图中按层级提取数据。
Args:
source (list): 起始节点列表。
target (list): 目标节点列表,遇到这些节点时停止该路径的进一步遍历。
graph (dict): 表示图的字典,键是节点,值是其邻居列表。
Returns:
dict: 一个字典,键是层级编号,值是该层级中提取的节点及其邻居。
"""
queue = deque((0, node) for node in source) # 队列存储 (层级, 节点) 对
target_set = set(target) # 转换为集合以提高查找效率
seen = set(source) # 记录已访问节点,防止循环和重复处理
result = {} # 存储最终结果
while queue:
level, node = queue.popleft() # 弹出当前层级和节点
# 确保当前层级的字典已初始化
result.setdefault(level, {})
# 提取当前节点的邻居
neighbors = graph.get(node, [])
result[level][node] = neighbors.copy() # 将节点及其邻居添加到结果中
for neighbor in neighbors:
# 如果邻居已访问过,或者邻居是目标节点,则不再进一步遍历此路径
if neighbor in seen or neighbor in target_set:
continue
seen.add(neighbor) # 标记为已访问
queue.append((level + 1, neighbor)) # 将邻居及其下一层级加入队列
return result
# 示例数据
source_list = ['a', 'b']
target_list = ['x', 'y', 'z']
my_dict = {
'a': ['e'],
'b': ['f', 'd'],
'e': ['g'],
'f': ['t', 'h'],
'd': ['x'],
'g': ['x'],
't': ['y'],
'h': ['z']
}
# 运行并打印结果
output = bfs_extract_levels(source_list, target_list, my_dict)
print(output)输出:
{0: {'a': ['e'], 'b': ['f', 'd']}, 1: {'e': ['g'], 'f': ['t', 'h'], 'd': ['x']}, 2: {'g': ['x'], 't': ['y'], 'h': ['z']}}在某些场景下,为了更清晰地组织代码或针对特定性能需求,我们可以优化层级构建的方式,即在每次循环中处理完一个完整层级的所有节点。
from collections import deque
def build_level_dict(graph, queue, seen, target_set):
"""
辅助函数:构建当前层级的字典。
"""
# 标记当前层级队列的末尾,以便知道何时停止处理当前层级
# 注意:这里假设queue在传入时已经包含了当前层级的所有节点
# 且这些节点在seen中已标记。
tail_of_current_level = queue[-1] if queue else None
level_dict = {}
while True:
if not queue: # 如果队列为空,且没有tail,说明已经处理完所有
break
node = queue.popleft()
neighbors = graph.get(node, [])
level_dict[node] = neighbors.copy()
for neighbor in neighbors:
if neighbor in seen or neighbor in target_set:
continue
seen.add(neighbor)
queue.append(neighbor)
# 当处理到当前层级的最后一个节点时,返回该层级的字典
if node == tail_of_current_level:
return level_dict
return level_dict # 如果队列为空,直接返回
def bfs_optimized_extract_levels(source, target, graph):
"""
使用优化后的广度优先搜索从图中按层级提取数据。
每次循环处理一个完整的层级。
"""
target_set = set(target)
result = {}
# 初始层级的所有节点都标记为已访问,并加入队列
seen = set(source)
queue = deque(source)
level = 0
while queue:
# 调用辅助函数构建当前层级的字典
result[level] = build_level_dict(graph, queue, seen, target_set)
level += 1
return result
# 示例数据 (与之前相同)
source_list = ['a', 'b']
target_list = ['x', 'y', 'z']
my_dict = {
'a': ['e'],
'b': ['f', 'd'],
'e': ['g'],
'f': ['t', 'h'],
'd': ['x'],
'g': ['x'],
't': ['y'],
'h': ['z']
}
# 运行并打印结果
output_optimized = bfs_optimized_extract_levels(source_list, target_list, my_dict)
print(output_optimized)输出:
{0: {'a': ['e'], 'b': ['f', 'd']}, 1: {'e': ['g'], 'f': ['t', 'h'], 'd': ['x']}, 2: {'g': ['x'], 't': ['y'], 'h': ['z']}}优化说明:
这个优化版本通过 build_level_dict 函数,在一个内部循环中处理完当前层级的所有节点。它通过在进入 build_level_dict 时记录队列的 tail(即当前层级最后一个加入队列的节点),来判断何时结束当前层级的处理。当 node == tail_of_current_level 时,表示当前层级的所有节点都已处理完毕,可以返回该层级的 level_dict。这种方式可以使主循环的逻辑更专注于层级递增,而层级内部的细节则由辅助函数封装。在某些情况下,这种结构可能在处理大量节点时略微提高效率,因为它减少了每次弹出节点时对层级变量的更新操作,并更集中地处理一个层级的数据。
本教程详细展示了如何利用 Python 中的广度优先搜索 (BFS) 算法,有效地从一个表示图结构的字典中,按层级提取数据。我们通过两种不同的实现方式,包括一个标准版本和一个优化版本,解决了从 source_list 开始,逐层遍历并收集相关节点及其邻居,直到遇到 target_list 中的节点为止的问题。
核心要点包括:
掌握这些技术,您将能够更灵活地处理复杂的图数据结构,并根据业务需求进行高效的数据提取和组织。
以上就是Python 中基于广度优先搜索 (BFS) 的多层级字典数据提取教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号