Menu
Coddy logo textTech

BFS (visita in ampiezza)

Ultimo aggiornamento

La visita in ampiezza esplora un grafo livello per livello. Partendo da un nodo sorgente, visita prima tutti i suoi vicini diretti, poi tutti i loro vicini non ancora visitati e così via, espandendosi verso l'esterno in anelli di distanza crescente. Premi play qui sopra per vederla allargarsi dal nodo di partenza uno strato alla volta.

La BFS usa una coda FIFO (first-in-first-out), ed è questa a imporre l'ordine livello per livello. Dato che raggiunge i nodi in ordine di distanza in salti, la BFS trova il cammino minimo (meno archi) in un grafo non pesato. Visita ogni nodo e ogni arco una volta, quindi richiede tempo O(V + E).

Complessità temporale e spaziale

MisuraComplessitàNote
TempoO(V + E)Ogni vertice e ogni arco visitati una volta
SpazioO(V)Coda + insieme dei visitati, nel caso peggiore tutti i nodi
VisitaLivello per livelloPrima i nodi più vicini, ad anelli
Cammino minimoSì (non pesato)Raggiunge ogni nodo con il minor numero di archi

Passo dopo passo

PassoCosa succede
1Metti in coda il nodo sorgente.
2Estrai il nodo in testa alla coda e segnalo come visitato.
3Esamina ciascuno dei suoi vicini.
4Metti in coda ogni vicino non ancora visitato né in coda.
5Ripeti finché la coda non è vuota.

Esempio svolto

Visita di questo grafo dal nodo 0, dove gli archi sono 0-1, 0-2, 1-3, 2-3, 2-4:

PassoVisitatiCoda (frontiera)
Inizio{}[0]
Estrai 0{0}[1, 2]
Estrai 1{0, 1}[2, 3]
Estrai 2{0, 1, 2}[3, 4]
Estrai 3{0, 1, 2, 3}[4]
Estrai 4{0, 1, 2, 3, 4}[] (fatto)

Quando usare la BFS

Usala quandoEvitala quando
Ti serve il cammino minimo in un grafo non pesatoGli archi hanno pesi: usa invece Dijkstra
È probabile che la destinazione sia vicina alla sorgenteIl grafo è molto largo: la coda può contenere una frontiera enorme
Vuoi esplorare un grafo per livelliTi basta raggiungere un nodo qualsiasi, e la DFS usa meno memoria
Cerchi le componenti connesse o un percorso con il minimo di saltiTi serve un ordinamento topologico o il rilevamento di cicli: la DFS è più adatta

BFS e DFS a confronto

Entrambe visitano ogni nodo in O(V + E), ma l'ordine e la struttura dati cambiano. Guarda la visualizzazione della visita in profondità per confrontarle fianco a fianco.

AspettoBFSDFS
Struttura datiCoda (FIFO)Pila / ricorsione
OrdineLivello per livello (prima i più vicini)In profondità lungo un ramo, poi torna indietro
Cammino minimo (non pesato)Sì: meno archiNo: non garantito
Memoria su grafi larghiAlta: la frontiera può essere enormeBassa: un percorso alla volta
Ideale perMinimo numero di salti, componenti connesseRilevamento di cicli, ordinamento topologico, backtracking

Un'implementazione di Breadth-First Search pulita ed eseguibile in Python, JavaScript, Java, C++, C. Scegli un linguaggio, copia il codice o aprilo già caricato nel Playground di Coddy.

Codice Breadth-First Search in Python

Python
1from collections import deque2
3
4def bfs(graph, start):5    visited = {start}6    queue = deque([start])7    order = []8    while queue:9        node = queue.popleft()10        order.append(node)11        for neighbor in graph[node]:12            if neighbor not in visited:13                visited.add(neighbor)  # mark on enqueue, not dequeue14                queue.append(neighbor)15    return order16
17
18graph = {19    "A": ["B", "C"],20    "B": ["D", "E"],21    "C": ["F"],22    "D": [],23    "E": ["F"],24    "F": [],25}26
27print("BFS order:", " -> ".join(bfs(graph, "A")))
Esegui questo codice nel playground Python

Domande frequenti sulla BFS

Qual è la complessità temporale della BFS?
La BFS richiede tempo O(V + E), dove V è il numero di vertici ed E il numero di archi, perché visita ogni vertice una volta ed esamina ogni arco una volta. Usa spazio O(V) per la coda e l'insieme dei visitati.
La BFS trova il cammino minimo?
Sì, in un grafo non pesato. Dato che la BFS raggiunge i nodi in ordine di distanza in salti dalla sorgente, la prima volta che raggiunge un nodo lo fa lungo un percorso con il minor numero di archi. Per i grafi pesati ti serve invece l'algoritmo di Dijkstra.
Qual è la differenza tra BFS e DFS?
La BFS usa una coda ed esplora livello per livello (prima i più vicini), mentre la DFS usa una pila e scende in profondità lungo un ramo prima di tornare indietro. La BFS trova i cammini minimi non pesati; la DFS usa meno memoria sui grafi larghi ed è adatta al rilevamento di cicli e all'ordinamento topologico.
Quando conviene usare la BFS invece dell'algoritmo di Dijkstra?
Usa la BFS quando ogni arco ha lo stesso costo, perché trova il percorso con meno archi in tempo O(V + E) senza una coda di priorità. L'algoritmo di Dijkstra serve quando gli archi hanno pesi diversi; eseguire una semplice BFS su un grafo pesato dà il percorso con meno salti, non quello di costo minimo.
Perché la BFS ha bisogno di un insieme dei visitati?
I grafi possono contenere cicli, quindi senza un insieme dei visitati la BFS metterebbe in coda lo stesso nodo più volte e girerebbe all'infinito. Segnare un nodo quando lo metti in coda per la prima volta (non quando lo estrai) evita anche che lo stesso nodo venga aggiunto due volte alla coda da vicini diversi.
Devo segnare un nodo come visitato quando lo metto in coda o quando lo estraggo?
Segnalo quando lo metti in coda. Se aspetti di estrarlo, un nodo può essere aggiunto alla coda più volte da vicini diversi prima di essere elaborato, sprecando memoria e tempo. Segnarlo all'inserimento garantisce che ogni nodo entri in coda esattamente una volta.
Illustrazione dei linguaggi di programmazione di Coddy

Padroneggia gli algoritmi con Coddy

INIZIA