WhatsApp

  

Algoritmo de Búsqueda en Anchura (BFS) en Grafos: Conceptos, Implementación en Python y Mejores Prácticas

Guía completa sobre el algoritmo BFS: teoría, implementación paso a paso en Python, comparativas con DFS, análisis de complejidad, casos de uso reales y recomendaciones de optimización.

Algoritmo de Búsqueda en Anchura (BFS) en Grafos

Introducción

La búsqueda en anchura (Breadth‑First Search, BFS) es uno de los algoritmos fundamentales para recorrer o explorar grafos. Se utiliza cuando se necesita encontrar la ruta más corta en grafos no ponderados, detectar componentes conectados o generar niveles jerárquicos (por ejemplo, en árboles de decisión).

En este artículo profundizaremos en su funcionamiento, veremos una implementación completa en Python 3.11+, compararemos sus características con la búsqueda en profundidad (DFS) y ofreceremos buenas prácticas para su uso en entornos de producción.

Fundamentos teóricos de BFS

  • Estructura de datos principal: una cola FIFO que garantiza que los nodos se procesen en el orden de su descubrimiento.
  • Orden de visita: nivel por nivel, es decir, todos los vértices a distancia d del origen se visitan antes que los de distancia d+1.
  • Complejidad temporal: O(|V| + |E|), donde |V| es el número de vértices y |E| el número de aristas.
  • Complejidad espacial: O(|V|) para almacenar el conjunto de vértices visitados y la cola.

Implementación paso a paso en Python

A continuación se muestra una versión idiomática que utiliza collections.deque y tipado estático con typing para mayor claridad.

from __future__ import annotations
import collections
from typing import Dict, List, Set, Tuple
# Tipo alias para mayor legibilidad
Graph = Dict[int, List[int]]
def bfs(graph: Graph, start: int) -> Tuple[List[int], Dict[int, int]]:
    """Recorre graph desde start usando BFS.
    Devuelve una lista con el orden de visita y un diccionario que
    mapea cada nodo a su distancia (número de aristas) desde start.
    """
    visited: Set[int] = set()
    distance: Dict[int, int] = {start: 0}
    order: List[int] = []
    queue: collections.deque[int] = collections.deque([start])
    visited.add(start)
    while queue:
        vertex = queue.popleft()
        order.append(vertex)
        for neighbour in graph.get(vertex, []):
            if neighbour not in visited:
                visited.add(neighbour)
                distance[neighbour] = distance[vertex] + 1
                queue.append(neighbour)
    return order, distance
# Ejemplo de uso ----------------------------------------------------------
if __name__ == "__main__":
    sample_graph: Graph = {
        1: [2, 3],
        2: [4, 5],
        3: [6],
        4: [],
        5: [6],
        6: []
    }
    order, dist = bfs(sample_graph, 1)
    print("Orden de visita:", order)
    print("Distancias desde 1:", dist)

Salida esperada:

Orden de visita: [1, 2, 3, 4, 5, 6]
Distancias desde 1: {1: 0, 2: 1, 3: 1, 4: 2, 5: 2, 6: 2}

Comparativa rápida: BFS vs DFS

BFS (Breadth‑First Search)

  • Explora por niveles.
  • Ideal para caminos más cortos en grafos no ponderados.
  • Uso de cola FIFO.
  • Mayor consumo de memoria en grafos amplios.

DFS (Depth‑First Search)

  • Explora profundizando en cada rama.
  • Útil para topological sort, detección de ciclos.
  • Uso de pila (recursiva o explícita).
  • Menor consumo de memoria, pero no garantiza el camino más corto.

Casos de uso en el mundo real

  1. Redes sociales: cálculo de grados de separación entre usuarios.
  2. Sistemas de recomendación: exploración de grafos de productos para encontrar ítems a distancia mínima.
  3. Juegos de tablero: generación de movimientos posibles en el número mínimo de turnos.
  4. Algoritmos de routing: protocolos como OSPF utilizan BFS para construir árboles de menor coste en topologías no ponderadas.

Mejores prácticas y optimizaciones

  • Usar deque en lugar de listas: la operación popleft() es O(1).
  • Evitar la recursión: BFS no se adapta a recursión; usar estructuras iterativas previene desbordamiento de pila.
  • Limitar la profundidad: en grafos muy extensos, aplicar un depth limit para evitar recorridos infinitos en grafos cíclicos.
  • Persistencia de resultados: almacenar distancias en una base de datos (ej. Redis) cuando se reutilizan consultas frecuentes.
  • Paralelismo: en grafos masivos, dividir la cola entre varios workers (ej. con multiprocessing o Ray) manteniendo un conjunto de nodos ya visitados thread‑safe.

Resolución de problemas comunes

ProblemaPosible causaSolución
Algoritmo no terminaGrafos con ciclos y falta de marcaje de nodos visitadosAsegúrate de mantener un set de vértices visitados antes de encolar.
Memoria excesivaCola crece demasiado por grafos densosImplementa un frontier pruning o usa BFS bidireccional cuando buscas un camino entre dos nodos.
Distancias incorrectasActualización de la distancia fuera de ordenIncrementa la distancia en base al nodo sacado de la cola, no al vecino.

Compatibilidad, rendimiento y escalabilidad

El algoritmo BFS es independiente del lenguaje, pero su rendimiento varía según la implementación de la cola y la estructura de grafo:

  • Python: deque es la opción más rápida; evita listas con pop(0).
  • C / C++: std::queue o std::deque ofrecen O(1) amortizado.
  • Java: ArrayDeque supera a LinkedList en operaciones de inserción y extracción.

Para grafos con cientos de millones de nodos, considera:

  1. Almacenar el grafo en una base de datos de grafos (Neo4j, Amazon Neptune) y delegar la expansión de vecinos al motor.
  2. Utilizar BFS distribuido (ej. Pregel, Apache Giraph).

Conclusión

La búsqueda en anchura es una herramienta esencial para cualquier ingeniero de datos, científico de datos o desarrollador de backend que trabaje con grafos. Su simplicidad, garantizada optimalidad en caminos más cortos y facilidad de paralelización la convierten en la elección predeterminada en numerosos escenarios productivos.

Dominar su implementación en Python y comprender sus trade‑offs frente a DFS permitirá diseñar soluciones robustas y escalables.



Algoritmo de Búsqueda en Anchura (BFS) en Grafos: Conceptos, Implementación en Python y Mejores Prácticas
ASIMOV Ingeniería S. de R.L. de C.V., Emiliano Nava 15 noviembre, 2025
Compartir
Iniciar sesión dejar un comentario

  
Algoritmo de Búsqueda en Profundidad (DFS) en Grafos – Guía Completa y Ejemplos en Python
Aprende todo sobre el algoritmo DFS: teoría, implementaciones recursivas e iterativas en Python, comparativas, casos de uso, optimizaciones y buenas prácticas para trabajar con grafos.