web-dev-qa-db-fra.com

Python Implémenter la recherche en largeur d'abord

J'ai trouvé un exemple en ligne, cependant, renvoyer uniquement la séquence des éléments BFS n'est pas suffisant pour le calcul. Disons que la racine est le premier niveau de l'arbre BFS, puis ses enfants sont le deuxième niveau, etc. Comment puis-je savoir à quel niveau ils se trouvent et qui est le parent de chaque nœud à partir du code ci-dessous (je vais créer un objet pour stocker son niveau parent et arbre)?

# 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']
7
user5575144

Vous pouvez suivre les niveaux de chaque nœud en affectant d'abord le niveau 0 au nœud de départ. Ensuite, pour chaque voisin du nœud X attribuez le niveau level_of_X + 1.

De plus, votre code pousse le même nœud plusieurs fois dans la file d'attente. J'ai utilisé une liste séparée visited pour éviter cela.

# 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)
8
Anonta

Ouais, ce code ne visite les nœuds que d'une manière très large. Ceci est en soi une chose utile à faire pour de nombreuses applications (par exemple, trouver les chemins les plus courts dans un graphique non pondéré)

Pour retourner réellement l'arborescence BFS, il faudrait du travail supplémentaire. Vous pouvez penser à stocker une liste d'enfants pour chaque nœud, ou à renvoyer des paires de (nœud, parent-nœud). L'une ou l'autre représentation devrait vous permettre de comprendre la structure de l'arbre.

Une autre chose à noter ici, c'est que le code utilise python listes comme file d'attente, ce qui n'est pas une bonne idée. Parce que la suppression du premier élément d'une liste, nécessite O(n) fois.

2
Shalan