DFS (depth-first search - búsqueda en profundidad) explora un camino hasta el fondo antes de retroceder. Resulta clave para detectar ciclos, obtener orden topológico y clasificar aristas.
Se parte de un vértice origen, se marca como visitado y se recorre recursiva o iterativamente cada vecino no visitado antes de regresar. El proceso se repite para cubrir todos los componentes.
def dfs_rec(g, u, visitado):
visitado[u] = True
print(u, end=" ")
for v, _ in g[u]:
if not visitado[v]:
dfs_rec(g, v, visitado)
def dfs(g, origen):
visitado = {v: False for v in g}
dfs_rec(g, origen, visitado)
def dfs_iterativo(g, origen):
visitado = {v: False for v in g}
pila = [origen]
while pila:
u = pila.pop()
if visitado[u]:
continue
visitado[u] = True
print(u, end=" ")
for v, _ in g[u]:
if not visitado[v]:
pila.append(v)
Durante DFS se puede registrar el padre y el tiempo de descubrimiento de cada vértice para clasificar aristas en:
Programa autocontenido que construye un grafo pequeño y ejecuta DFS recursivo e iterativo.
def dfs_rec(g, u, visitado):
visitado[u] = True
print(u, end=" ")
for v, _ in g[u]:
if not visitado[v]:
dfs_rec(g, v, visitado)
def dfs(g, origen):
visitado = {v: False for v in g}
dfs_rec(g, origen, visitado)
def dfs_iterativo(g, origen):
visitado = {v: False for v in g}
pila = [origen]
while pila:
u = pila.pop()
if visitado[u]:
continue
visitado[u] = True
print(u, end=" ")
for v, _ in g[u]:
if not visitado[v]:
pila.append(v)
def main():
g = {
0: [(1, 1), (2, 1)],
1: [(0, 1), (3, 1)],
2: [(0, 1), (4, 1)],
3: [(1, 1), (4, 1)],
4: [(2, 1), (3, 1)]
}
print("DFS recursivo desde 0: ", end="")
dfs(g, 0)
print()
print("DFS iterativo desde 0: ", end="")
dfs_iterativo(g, 0)
print()
if __name__ == "__main__":
main()
Ejecuta para comparar el orden de visita entre DFS recursivo e iterativo. Modifica las aristas para ver cómo cambian los recorridos. Con el grafo definido y empujando vecinos en el orden en que aparecen, una salida posible es:
DFS recursivo desde 0: 0 2 4 1 3
DFS iterativo desde 0: 0 1 3 4 2
El orden de la versión iterativa cambia según la pila y el orden en que se apilan los vecinos; si se invierte la inserción en la pila puede igualarse al orden recursivo.