networkx图论Breadth First Search广度优先搜索遍历BFS,基于队列,Python

x33g5p2x  于2021-11-11 转载在 Python  
字(1.8k)|赞(0)|评价(0)|浏览(653)

Breadth First Search,广度优先搜索(遍历),BFS实现一般基于队列。队列在广度优先搜索遍历中是关键点。

(1)队列Q在弹出最左边头部的节点V的同时,要把与V邻接的子节点立即加入队列Q的尾部。然后在while循环中重复处理(弹出最最左边头部的节点)。直到队列的长度为0,循环结束,也即算法完成遍历搜索。

(2)本例基于networkx实现,networkx提供了节点、图、边的现成工具,只需要按照需要记录节点的访问情况,当每一个节点作为顶点被弹出时候,标记它为已访问(visited=true),全图搜索路径由此产生。

一个例子:

import networkx as nx
import matplotlib.pyplot as plt

from collections import deque

# 记录搜索路径
search_path = []

def my_graph():
    G = nx.gnm_random_graph(n=6, m=8)
    # G = nx.balanced_tree(r=2, h=3)

    pos = nx.spring_layout(G)
    nx.draw_networkx(G, pos,
                     node_color='green',
                     node_size=300,
                     font_size=10,
                     font_color='white',
                     edge_color='gray',
                     width=1,
                     with_labels=True)

    print('G.nodes(data=True)', G.nodes(data=True))

    bfs(G)

    plt.show()

# 基于队列实现广度优先遍历
def bfs(G):
    for n in G.nodes():
        G.nodes[n]['visited'] = False
    print(G.nodes(data=True))

    V = 0
    Q = deque()
    Q.append(V)
    while True:
        if len(Q) == 0:
            break

        print('-----')
        print('Q', Q)
        node = Q.popleft()  # 左边最头部含有上一轮父层次的节点
        print('弹出', node)
        G.nodes[node]['visited'] = True

        search_path.append(node)
        print('search_path', search_path)

        for n in nx.neighbors(G, node):
            # 注意,如果n已经在队列里面,则不予重复添加。
            if (not G.nodes[n]['visited']) and (n not in Q):
                Q.append(n)

        print('Q append', Q)

    # print('search_path', search_path)

    print('=====')
    print('\n标准的networkx广度优先搜索:')
    print(list(nx.bfs_tree(G, source=0)))

if __name__ == '__main__':
    my_graph()

生成图:

运行日志:

G.nodes(data=True) [(0, {}), (1, {}), (2, {}), (3, {}), (4, {}), (5, {})]
[(0, {'visited': False}), (1, {'visited': False}), (2, {'visited': False}), (3, {'visited': False}), (4, {'visited': False}), (5, {'visited': False})]
-----
Q deque([0])
弹出 0
search_path [0]
Q append deque([1, 3, 4])
-----
Q deque([1, 3, 4])
弹出 1
search_path [0, 1]
Q append deque([3, 4, 5])
-----
Q deque([3, 4, 5])
弹出 3
search_path [0, 1, 3]
Q append deque([4, 5])
-----
Q deque([4, 5])
弹出 4
search_path [0, 1, 3, 4]
Q append deque([5, 2])
-----
Q deque([5, 2])
弹出 5
search_path [0, 1, 3, 4, 5]
Q append deque([2])
-----
Q deque([2])
弹出 2
search_path [0, 1, 3, 4, 5, 2]
Q append deque([])
=====

标准的networkx广度优先搜索:
[0, 1, 3, 4, 5, 2]

相关文章