オンラインで例を見つけましたが、BFS要素のシーケンスのみを返すだけでは計算には不十分です。ルートがBFSツリーの最初のレベルであり、その子が2番目のレベルなどであるとしましょう。以下のコードから、各ノードの親と各ノードの親をどのように知ることができますか(オブジェクトを作成しますその親とツリーレベルを保存します)?
# sample graph implemented as a dictionary
graph = {'A': ['B', 'C', 'E'],
'B': ['A','D', 'E'],
'C': ['A', 'F', 'G'],
'D': ['B'],
'E': ['A', 'B','D'],
'F': ['C'],
'G': ['C']}
# visits all the nodes of a graph (connected component) using BFS
def bfs_connected_component(graph, start):
# keep track of all visited nodes
explored = []
# keep track of nodes to be checked
queue = [start]
# keep looping until there are nodes still to be checked
while queue:
# pop shallowest node (first node) from queue
node = queue.pop(0)
if node not in explored:
# add node to list of checked nodes
explored.append(node)
neighbours = graph[node]
# add neighbours of node to queue
for neighbour in neighbours:
queue.append(neighbour)
return explored
bfs_connected_component(graph,'A') # returns ['A', 'B', 'C', 'E', 'D', 'F', 'G']
最初にレベル0を開始ノードに割り当てることにより、各ノードのレベルを追跡できます。次に、ノードの各ネイバーに対してX
assign level level_of_X + 1
。
また、コードは同じノードをキューに複数回プッシュします。それを避けるために、別のリストvisited
を使用しました。
# sample graph implemented as a dictionary
graph = {'A': ['B', 'C', 'E'],
'B': ['A','D', 'E'],
'C': ['A', 'F', 'G'],
'D': ['B'],
'E': ['A', 'B','D'],
'F': ['C'],
'G': ['C']}
# visits all the nodes of a graph (connected component) using BFS
def bfs_connected_component(graph, start):
# keep track of all visited nodes
explored = []
# keep track of nodes to be checked
queue = [start]
levels = {} # this dict keeps track of levels
levels[start]= 0 # depth of start node is 0
visited= [start] # to avoid inserting the same node twice into the queue
# keep looping until there are nodes still to be checked
while queue:
# pop shallowest node (first node) from queue
node = queue.pop(0)
explored.append(node)
neighbours = graph[node]
# add neighbours of node to queue
for neighbour in neighbours:
if neighbour not in visited:
queue.append(neighbour)
visited.append(neighbour)
levels[neighbour]= levels[node]+1
# print(neighbour, ">>", levels[neighbour])
print(levels)
return explored
ans = bfs_connected_component(graph,'A') # returns ['A', 'B', 'C', 'E', 'D', 'F', 'G']
print(ans)
ええ、このコードは幅優先の方法でのみノードにアクセスします。これはそれ自体で多くのアプリケーションで行うのに便利です(たとえば、重みのないグラフで最短パスを見つける)
実際にBFSツリーを返すには、追加の作業が必要になります。各ノードの子のリストを保存するか、(node、parent-node)のペアを返すことを考えることができます。どちらの表現でも、ツリーの構造を把握できるはずです。
ここで注意すべきもう1つのことは、コードがpythonリストをキューとして使用することです。これはお勧めできません。リストから最初の要素を削除するには、O(n)時間。