Networkx:如何按广度优先方式遍历有向图(DiGraph)的所有边?
解决NetworkX有向图中按广度优先顺序遍历所有边的问题
我明白你的困扰——bfs_edges确实只会返回每个节点第一次被发现时的那条边,完全忽略了节点的其他前驱边,这显然不符合你要遍历所有边的需求。既然你的图里所有节点都能从源节点0到达,我们可以换个思路来实现按BFS顺序遍历所有边。
方案1:按BFS节点顺序遍历所有出边
如果你的需求是从源节点0开始,先处理0的所有出边,再处理第一层节点的所有出边,以此类推,那可以先通过BFS获取节点的访问顺序,再逐个遍历每个节点的所有出边:
import networkx as nx # 初始化你的有向图 G = nx.DiGraph() # 添加你的边列表(示例边仅供参考) edges = [(0, 1), (0, 2), (1, 3), (2, 3), (0, 3)] G.add_edges_from(edges) # 获取从0出发的BFS节点访问顺序 bfs_nodes = list(nx.bfs_tree(G, source=0).nodes()) # 按BFS顺序遍历所有出边并编辑属性 for node in bfs_nodes: for neighbor in G.neighbors(node): edge = (node, neighbor) # 这里可以编辑边的属性,比如设置weight为层级值 G.edges[edge]['weight'] = nx.shortest_path_length(G, 0, node) print(f"已处理边: {edge}")
这个方法的核心是先拿到BFS的节点访问序列,再对每个节点遍历它的所有出边,保证边的处理顺序严格遵循BFS的层级逻辑。
方案2:按BFS节点顺序遍历所有入边
如果你的需求是按节点被BFS发现的顺序,处理该节点的所有入边(比如节点3被发现后,一次性处理(0,3)、(1,3)、(2,3)所有入边),那可以这样实现:
import networkx as nx G = nx.DiGraph() edges = [(0, 1), (0, 2), (1, 3), (2, 3), (0, 3)] G.add_edges_from(edges) # 获取BFS节点顺序,跳过源节点0(它没有前驱边) bfs_nodes = list(nx.bfs_tree(G, source=0).nodes())[1:] # 按BFS节点顺序遍历所有入边并编辑属性 for node in bfs_nodes: for predecessor in G.predecessors(node): edge = (predecessor, node) # 这里编辑边属性,比如标记为已处理 G.edges[edge]['processed'] = True print(f"已处理边: {edge}")
这种方式会先处理第一层节点(1、2)的所有入边,再处理第二层节点3的所有入边,完全符合BFS的层级遍历顺序。
为什么bfs_edges不适用?
补充下背后的原因:nx.bfs_edges(G, source=0)的设计初衷是生成BFS树的边,它只会追踪每个节点第一次被访问时的路径,所以当节点有多个前驱时,只有第一条到达它的边会被返回,其他边都会被遗漏,这显然满足不了你遍历所有边的需求。
内容的提问来源于stack exchange,提问作者Clément F
相关产品推荐
相关产品推荐

