BFS explora un grafo por niveles: primero visita los vértices más cercanos al origen y después avanza hacia los más alejados. Para mantener este orden utiliza una cola.
El recorrido en anchura, conocido como BFS por Breadth-First Search, es uno de los algoritmos fundamentales para explorar grafos. A diferencia de DFS, que profundiza por una rama, BFS examina primero todos los vecinos inmediatos del origen.
Luego visita los vértices situados a dos aristas de distancia, después los que se encuentran a tres y así sucesivamente. Esta organización permite calcular caminos mínimos en grafos sin pesos.
BFS repite cuatro acciones:
El proceso termina cuando la cola queda vacía. En ese momento se han visitado todos los vértices alcanzables desde el origen.
BFS utiliza una cola, una estructura FIFO: el primer elemento que entra es el primero que sale (First In, First Out).
Si desde A se descubren B, C y D en ese orden, la cola garantiza que B se procese antes que C y C antes que D. Los vértices de un nivel se procesan antes de comenzar el nivel siguiente.
El nivel de un vértice es la cantidad mínima de aristas necesarias para llegar hasta él desde el origen. El origen pertenece al nivel 0, sus vecinos al nivel 1 y los vecinos nuevos de estos al nivel 2.
| Nivel | Distancia desde A | Ejemplo |
|---|---|---|
| 0 | 0 aristas | A |
| 1 | 1 arista | B, C, D |
| 2 | 2 aristas | E, F |
| 3 | 3 aristas | G |
Los vértices de un mismo nivel pueden cambiar de orden según cómo estén almacenados los vecinos, pero nunca se procesa un nivel posterior antes de finalizar los anteriores.
Selecciona un nodo como origen y pulsa Iniciar. Avanza paso a paso para observar la cola, el orden de visita, las distancias y las aristas del árbol BFS.
Cola
Orden de visita
Acción actual
Verde indica los vértices pendientes en la cola; celeste, los ya procesados; rosa, el vértice actual. El número de cada nodo representa su distancia al origen.
Un vértice debe marcarse como visitado en el momento de encolarlo, no cuando se lo retira de la cola. Así se evita que dos vértices distintos encolen al mismo vecino.
Marcar al desencolar puede generar duplicados, desperdiciar memoria y dificultar la construcción correcta del árbol BFS.
Cuando BFS descubre un vértice nuevo, registra la arista por la que llegó a él. Esas aristas forman un árbol con raíz en el origen.
El padre de cada vértice se encuentra en el nivel inmediatamente anterior. Por eso el camino desde la raíz hasta cualquier nodo del árbol utiliza la menor cantidad posible de aristas.
En un grafo no ponderado, o cuando todas las aristas tienen el mismo costo, BFS encuentra caminos mínimos en cantidad de aristas. La primera vez que se descubre un vértice se ha encontrado una ruta de longitud mínima hasta él.
Para reconstruir esa ruta se guarda el padre de cada nodo y se retrocede desde el destino hasta el origen.
Esta propiedad no se aplica directamente cuando las aristas tienen costos diferentes. En ese caso se necesitan algoritmos como Dijkstra o Bellman-Ford.
Una ejecución de BFS solo alcanza la componente que contiene al origen. Para recorrer todo un grafo desconectado debemos iniciar otra búsqueda desde cada vértice que continúe sin visitar.
Las aristas de descubrimiento forman entonces un bosque BFS, compuesto por un árbol para cada componente conexa.
function bfs(grafo, origen) {
const visitados = new Set([origen]);
const cola = [origen];
const orden = [];
while (cola.length > 0) {
const actual = cola.shift();
orden.push(actual);
for (const vecino of grafo[actual]) {
if (!visitados.has(vecino)) {
visitados.add(vecino); // marcar al encolar
cola.push(vecino);
}
}
}
return orden;
}
const grafo = {
A: ["B", "C"], B: ["A", "D"],
C: ["A", "D"], D: ["B", "C"]
};
console.log(bfs(grafo, "A")); // A, B, C, Dshift() facilita la explicación, pero desplaza los elementos del arreglo. Para colas grandes es más eficiente conservar un índice que indique el frente.
function caminoMinimoBFS(grafo, origen, destino) {
const cola = [origen];
const padre = new Map([[origen, null]]);
let frente = 0;
while (frente < cola.length) {
const actual = cola[frente++];
if (actual === destino) break;
for (const vecino of grafo[actual]) {
if (!padre.has(vecino)) {
padre.set(vecino, actual);
cola.push(vecino);
}
}
}
if (!padre.has(destino)) return null;
const camino = [];
for (let nodo = destino; nodo !== null; nodo = padre.get(nodo)) {
camino.push(nodo);
}
return camino.reverse();
}El mapa padre cumple dos funciones: indica qué vértices fueron descubiertos y permite reconstruir el camino. Si el destino no aparece en el mapa, no es alcanzable desde el origen.
Con listas de adyacencia, cada vértice se encola una sola vez y cada arista se examina una cantidad constante de veces. Por ello el tiempo es O(V + E) y el espacio adicional es O(V).
| Aplicación | Uso de BFS |
|---|---|
| Rutas sin pesos | Encontrar el camino con menos conexiones |
| Redes sociales | Calcular grados de separación |
| Laberintos | Hallar una salida con el mínimo número de pasos |
| Difusión en redes | Simular propagación por rondas |
| Grafos bipartitos | Colorear vértices alternando niveles |
| Conectividad | Obtener todos los nodos alcanzables |
| Característica | BFS | DFS |
|---|---|---|
| Estructura principal | Cola FIFO | Pila LIFO o recursión |
| Forma de explorar | Por niveles | Por ramas profundas |
| Camino mínimo sin pesos | Sí | No necesariamente |
| Memoria | Puede guardar una frontera amplia | Guarda principalmente el camino activo |
| Usos habituales | Distancias y cercanía | Ciclos, ordenamientos y retroceso |
Ninguno es universalmente mejor. La elección depende de si interesa explorar por cercanía, profundizar rápidamente o aprovechar una propiedad específica del problema.
shift() en colas muy grandes sin considerar su costo.BFS organiza la exploración según la distancia al origen. La cola preserva el orden de los niveles y convierte al algoritmo en una herramienta natural para conectividad, rutas mínimas sin pesos y procesos que avanzan por rondas.
En el próximo tema estudiaremos el ordenamiento topológico, que organiza los vértices de un grafo dirigido respetando sus dependencias.