Búsqueda en grafos: BFS y DFS
En 1736 Leonhard Euler demostró que ningún paseo cruza exactamente una vez cada uno de los siete puentes de Königsberg, y con esa respuesta empezó la teoría de grafos.
Puntos y líneas
Un grafo es un conjunto de puntos, llamados vértices o nodos, unidos por líneas, llamadas aristas. La idea es sencilla y sirve para muchísimas cosas: ciudades unidas por carreteras, páginas web unidas por enlaces, personas unidas por amistades, casillas de un laberinto unidas donde no hay pared. Una vez que un problema se dibuja como grafo, el mismo puñado de algoritmos puede responder preguntas como "¿puedo llegar de aquí a allá?" y "¿cuál es el camino más corto?".
Guardar un grafo en el código
Una forma común de guardar un grafo es una lista de adyacencia: para cada vértice, una lista de sus vecinos. Las notas del 6.006 del MIT usan exactamente esto, un arreglo o diccionario Adj donde Adj[u] enumera los vértices unidos a u. Para el grafo de arriba queda así:
const graph = { // lista de adyacencia
A: ["B", "C"],
B: ["A", "D"],
C: ["A", "D", "E"],
D: ["B", "C", "F"],
E: ["C", "F"],
F: ["D", "E"],
};Búsqueda en anchura: anillo por anillo
La búsqueda en anchura (BFS) explora un grafo en anillos alrededor del inicio. Primero el propio inicio, a distancia 0. Luego todos sus vecinos, a distancia 1. Luego cada vértice nuevo junto a esos, a distancia 2, y así sucesivamente. Para hacerlo usa una cola, una fila donde el primero en entrar es el primero en salir. Toma el vértice del frente de la cola, lo visita y agrega al final sus vecinos no vistos. Desde A en el ejemplo, BFS visita A, luego B y C, luego D y E, luego F. Como avanza hacia fuera de anillo en anillo, la primera vez que BFS llega a un vértice ha encontrado un camino con el menor número de aristas. F está a 3 aristas de A, por ejemplo A, B, D, F.
function bfs(graph, start) {
const seen = new Set([start]);
const queue = [start];
const order = [];
while (queue.length) {
const u = queue.shift(); // primero en entrar, primero en salir
order.push(u);
for (const v of graph[u]) {
if (!seen.has(v)) { seen.add(v); queue.push(v); }
}
}
return order; // A B C D E F
}Búsqueda en profundidad: todo lo lejos que puedas, y luego retroceder
La búsqueda en profundidad (DFS) se comporta como una persona en un laberinto que mantiene una mano en la pared. Sigue un camino lo más hondo posible. Cuando llega a un callejón sin salida o a un lugar que ya vio, retrocede al punto de decisión más reciente y prueba la siguiente opción. Usa una pila en lugar de una cola, último en entrar, primero en salir, y es muy natural escribirla con recursión, donde la pila de llamadas se encarga de recordar. Desde A, una DFS recursiva visita A, B, D, C, E, F. DFS llega a todos los vértices a los que llega BFS, pero el camino que sigue no es necesariamente el más corto.
function dfs(graph, u, seen = new Set(), order = []) {
seen.add(u);
order.push(u);
for (const v of graph[u]) if (!seen.has(v)) dfs(graph, v, seen, order);
return order; // orden: A B D C E F
}Arrastra para girar. Desplaza o pellizca para acercar.
Cuál usar
En el primer laberinto del laboratorio, BFS visita 105 casillas y encuentra un camino de 22 movimientos, el más corto posible. DFS se lanza por casualidad hacia la meta y visita solo 31 casillas, pero su camino lleva 28 movimientos. Ninguna es siempre más barata. Las dos tratan cada vértice y cada arista un número fijo de veces, así que las dos se ejecutan en tiempo O(V + E) para V vértices y E aristas. Elige BFS cuando necesites el menor número de pasos: los menos movimientos en un rompecabezas, los menos enlaces entre dos personas. Elige DFS cuando necesites explorarlo todo o seguir las decisiones hasta el final: comprobar si todas las habitaciones de un laberinto están conectadas, o probar las jugadas de un rompecabezas línea por línea y retroceder al atascarte. Cuando las aristas tienen longitudes distintas, como las carreteras, ninguna basta por sí sola; métodos como el algoritmo de Dijkstra amplían la idea de BFS con distancias.
| grafo | Vértices unidos por aristas |
| vértice (nodo) | Un punto de un grafo |
| arista | Una línea que une dos vértices |
| lista de adyacencia | Para cada vértice, la lista de sus vecinos |
| cola | Primero en entrar, primero en salir; la usa BFS |
| BFS | Búsqueda en anchura: anillo por anillo; encuentra caminos con el menor número de aristas |
| DFS | Búsqueda en profundidad: primero a fondo, luego retrocede; usa una pila |
| O(V + E) | El tiempo de ejecución de BFS y DFS |
- En el grafo de ejemplo, ¿cuántas aristas tiene el camino más corto de A a F?
- ¿Cuántas aristas tiene el grafo de ejemplo?
- ¿Qué estructura de datos usa la búsqueda en anchura?
- Una cola (primero en entrar, primero en salir)
- Una pila (último en entrar, primero en salir)
- Una lista ordenada
- Ninguna estructura
- ¿Qué búsqueda garantiza encontrar un camino con el menor número de aristas?
- BFS
- DFS
- Las dos, siempre
- Ninguna
- Ordena los vértices según los visita BFS desde A (tomando los vecinos en orden alfabético).
- Ordena los vértices según los visita una DFS recursiva desde A (vecinos en orden alfabético).
- En la cuadrícula de 15 por 9 del laboratorio, sin ninguna pared, ¿cuántos movimientos tiene el camino más corto de S (arriba a la izquierda) a G (abajo a la derecha)?
- ¿Por qué BFS y DFS deben recordar qué vértices ya vieron?
- Si no, un ciclo en el grafo haría que la búsqueda diera vueltas para siempre
- Para imprimirlos al final
- Para ordenarlos
- Solo hace falta en DFS
- ¿En qué año resolvió Euler el problema de los puentes de Königsberg?
- 1683
- 1736
- 1843
- 1945
- ¿Cuál es el tiempo de ejecución de BFS en un grafo con V vértices y E aristas?
- O(V + E)
- O(V × E)
- O(log V)
- O(2ⱽ)
- Quieres saber el menor número de enlaces de amigo de un amigo entre dos personas en una red social. ¿Qué búsqueda usas?
- BFS
- DFS
- Búsqueda binaria
- Ordenamiento por mezcla
- Un grafo son vértices unidos por aristas; las listas de adyacencia lo guardan.
- BFS usa una cola, avanza anillo por anillo y encuentra caminos con el menor número de aristas.
- DFS usa una pila (o recursión), va primero a fondo y luego retrocede.
- Las dos se ejecutan en O(V + E) y deben recordar los vértices vistos.
- La solución de Euler de 1736 a los puentes de Königsberg dio inicio a la teoría de grafos.
Fuentes de este curso (11)
- MIT OpenCourseWare 6.006 Introduction to Algorithms, Spring 2020 (Demaine, Ku, Solomon)
- lecture notes 1 Introduction, 3 Sorting, 9 Breadth-First Search, 10 Depth-First Search (ocw.mit.edu/courses/6-006-introduction-to-algorithms-spring-2020/pages/lecture-notes) and Fall 2011 lecture 13 BFS notes (ocw.mit.edu/courses/6-006-introduction-to-algorithms-fall-2011)
- Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms (MIT Press)
- with the CLRS-based Khan Academy algorithms unit by Thomas Cormen and Devin Balkcom of Dartmouth (khanacademy.org/computing/computer-science/algorithms: binary search, selection sort analysis, merge sort, quicksort overview and analysis)
- MacTutor History of Mathematics, Al-Khwarizmi (mathshistory.st-andrews.ac.uk/Biographies/Al-Khwarizmi: word algorithm from the Latin title Algoritmi de numero Indorum)
- D. E. Joyce, Euclid's Elements Book VII Propositions 1 and 2 (mathcs.clarku.edu/~djoyce/elements/bookVII)
- Wolfram MathWorld, Merge Sort (mathworld.wolfram.com/MergeSort.html: proposed by John von Neumann in 1945, after Knuth 1998 p. 159)
- Stanford CS "Tony Hoare: Quicksort" (cs.stanford.edu/people/eroberts/courses/soco/projects/2008-09/tony-hoare/quicksort.html: devised while a student at Moscow State University for Russian-English machine translation with a tape dictionary, programmed in Algol 60 and published 1961; the year 1959 from the Wikipedia Quicksort article and its cited sources)
- Bodleian Libraries, Ada Lovelace (blogs.bodleian.ox.ac.uk/adalovelace: 1843 paper, Note G Bernoulli numbers)
- Fourmilab text of Menabrea's Sketch with Lovelace's notes (fourmilab.ch/babbage/sketch.html)
- Seven Bridges of Konigsberg (Euler 1736) and Tower of Hanoi (Edouard Lucas, 1883) checked against the Wikipedia articles and their cited sources.
Fecha de consulta: 2026-10-17