Búsqueda en Profundidad (DFS) para Grafos: Enfoque Iterativo y Recursivo
Una implementación estándar de DFS coloca cada vértice del gráfico en una de las dos categorías, visitado o no visitado.
El objetivo del algoritmo es marcar cada vértice como visitado evitando los ciclos. En este algoritmo:
Se inicia colocando uno de los vértices del grafo en la parte superior de una pila.
Se toma el elemento superior de la pila y se añade a la lista de vértices visitados.
Se crea una lista de los nodos adyacentes a ese vértice.
Se añade los que no están en la lista de visitados a la parte superior de la pila.
Se repite los pasos 2 y 3 hasta que la pila esté vacía.
Solución recursiva:
Crear una función recursiva que tome el índice del nodo y un array visitado.
Marque el nodo actual como visitado e imprima el nodo.
Recorrer todos los nodos adyacentes y no marcados y llamar a la función recursiva con el índice del nodo adyacente.
Solución iterativa:
Primero se insertan todos los elementos en la pila y luego se hace uso de la cabeza de la pila (que es el último nodo insertado), así que el primer nodo que se maneja es el último hijo.
def dfs(raiz): pila =[] visitados =set() pila.append(raiz)whilepila: #comprueba si hay algo en la lista de tareas pendientes
nodoActual = pila.pop() # accede al nodo siguiente
if nodoActual not invisitados: # actualiza los nodos visitados si este nodo no habia sido visitado antes
visitados.add(nodoActual)for nodo in nodoActual.nodosAdyacentes: # itera sobre los nodos adyacentes
if nodo not invisitados: pila.append(nodo) # añade a la lista de tareas pendientes
classGraph:def__init__(self): self.adj_list ={}defadd_edge(self, u, v):if u notin self.adj_list: self.adj_list[u]=[]if v notin self.adj_list: self.adj_list[v]=[] self.adj_list[u].append(v) self.adj_list[v].append(u)
defdfs_iterative_search(grafo, inicio, valorAEncontrar): stack =[inicio]# Usamos una pila para el DFS visited =set()# Conjunto para evitar cicloswhile stack: node = stack.pop()if node in visited:continueprint(f"Visiting Node {node}") visited.add(node)if node == valorAEncontrar:print(f"Hemos encontrado el nodo {valorAEncontrar}!")return node
#(en orden inverso para mantener consistencia con DFS recursivo)for hijos inreversed(grafo.get(node,[])):if hijos notin visited: stack.append(hijos)print("Nodo no encontrado.")returnNone
module GrafosclassDfsServiceattr_reader:graph
def initialize(graph) @graph = graph
end
# DFS recursivo
def run_recursive(start) visited ={}dfs_rec(start, visited) visited.keys end
# DFS iterativo con pila
def run_iterative(start) visited ={} stack =[start] until stack.empty? node = stack.pop next if visited[node] visited[node]=true graph[node].eachdo|neighbor| stack << neighbor unless visited[neighbor] end
end
visited.keys end
private def dfs_rec(node, visited)returnif visited[node] visited[node]=true graph[node].eachdo|neighbor|dfs_rec(neighbor, visited) end
end
end
end
// CLASE NODOclassNodo{constructor(valor =null){this.valor= valor;this.hijos=[];}}// CLASE ARBOL/*
Para construir un arbol con raiz, con una profundidad dada y que todos
los nodos tengan el mismo número de hijos. El valor que contiene cada nodo es
su enumeracion con raiz.valor = 1 y asi sucesivamente.
*/classArbol{constructor(ramas =2,niveles =3){this.raiz=newNodo(1,null);this.ramas= ramas;this.niveles= niveles;this.vertices=0;}// Esta funcion se puede omitirobtener_numero_vertices(){for(let i =0; i <this.niveles;i++){this.vertices+=this.ramas**i;}returnthis.vertices;}// Esta funcion se puede omitirinfo(){console.log("Número de hijos por nodo: ",this.ramas);console.log("Número de niveles de profundidad: ",this.niveles);const n =this.obtener_numero_vertices();console.log("Número total de nodos: ", n);console.log("Número de aristas: ", n-1);}// La forma de crear los nodos se hace un recorrido similar al DFSconstruir_arbol(){console.log("--------Creación de árbol--------:")var pila =[[this.raiz,1]];var contador =2;while(pila.length>0){var[nodo_actual, nivel_actual]= pila.pop();console.log("Visitando nodo: "+ nodo_actual.valor+" (Nivel: "+ nivel_actual +")");if(nivel_actual <this.niveles){var siguiente_nivel = nivel_actual +1;for(let i =0; i <this.ramas; i++){var nuevoNodo =newNodo(contador); contador++; nodo_actual.hijos.push(nuevoNodo);console.log("Nodo "+ nuevoNodo.valor+" creado"); pila.push([nuevoNodo, siguiente_nivel]);}}}console.log("Se terminó de crear el árbol")}// La forma recorrer el árbol es similar al DFSimprimir(){console.log("--------Imprimir-------:")// por profundidad de derecha a izquierdavar pila =[this.raiz];var visitados =newSet();while(pila.length>0){var nodo_actual = pila.pop();if(visitados.has(nodo_actual.valor)){continue;}console.log("Visitando nodo: "+ nodo_actual.valor); visitados.add(nodo_actual.valor)var hijos = nodo_actual.hijos;for(let i =0; i < hijos.length;i++){console.log("Hijo: "+ hijos[i].valor); pila.push(hijos[i]);}}}// ITERATIVO// Deep Fisrt Search busqueda(objetivo){// por profundidad de derecha a izquierdaconsole.log("--------Busqueda de:"+ objetivo);var pila =[this.raiz];var visitados =newSet();while(pila.length>0){var nodo_actual = pila.pop();if(visitados.has(nodo_actual.valor)){continue;} visitados.add(nodo_actual.valor)if(nodo_actual.valor== objetivo){console.log("Encontramos el nodo!!");return nodo_actual;}var hijos = nodo_actual.hijos;for(let i =0; i < hijos.length;i++){ pila.push(hijos[i]);}}console.log("No lo encontramos");returnnull;}}// RECURSIVO // Deep Fisrt Search // Lo que se vio en la claseconstdfs=function(raiz, valorAEncontrar){console.log("En este momento estoy en el nodo que tiene el valor: "+ raiz.valor);if(raiz.valor== valorAEncontrar){console.log("Encontré el valor!");return raiz;}for(var i =0; i < raiz.hijos.length; i++){var nodoResultado =dfs(raiz.hijos[i], valorAEncontrar);if(nodoResultado!=null){return nodoResultado;}}returnnull;}// Para ejecutarloconst miarbol =newArbol(2,4);// puedes probar con otros parámetrosmiarbol.info();miarbol.construir_arbol();//miarbol.imprimir();miarbol.busqueda(8);dfs(miarbol.raiz,8);
My Little DFS with Stack as aux DS \n
/* DEPTH FIRST SEARCH AS DFS *//* GRAPH TRAVERSAL BY USING STACK AS DSA *//* VISITED ARRAY AS AUX LIST TO HANDLE VISITED NODES
AVOID VISIT VERTICES MULTIPLE TIME AS LOOP */constV=5;functiondfs(arr, source){var mstack =[];var isVisited =Array(V).fill(false); mstack.push(source); isVisited[source]=true;while(mstack.length){var node = mstack.pop();document.write("Visited Node: "+ node);for(var index =0; index <V; index++){if(arr[node][index]===1&& isVisited[index]===false){ mstack.push(index); isVisited[index]=true;}}}}// ADJ MATRIX OF GRAPH TRAVERSAL BY DFS ALGORITHM ...var arr =[[0,1,1,1,0],[1,0,0,1,1],[1,0,0,1,0],[1,1,1,0,1],[0,1,0,1,0]];document.write("DFS of the given graph is : ");dfs(arr,0);```/\*DEPTHFIRSTSEARCHASDFS \*/ /\* GRAPH TRAVERSAL BY USING STACK AS DSA \*//\*VISITEDARRAYASAUXLISTTOHANDLEVISITEDNODESAVOIDVISITVERTICESMULTIPLETIMEASLOOP \*/ constV=5;functiondfs(arr, source){ var mstack = \[];   var isVisited =Array(V).fill(false);  mstack.push(source);    isVisited\[source]=true; while(mstack.length){   var node = mstack.pop();   document.write("Visited Node: "+ node); for(var index =0; index <V; index++){   if(arr\[node]\[index]===1&& isVisited\[index]===false){    mstack.push(index);    isVisited\[index]=true;   }   }   }  }// ADJ MATRIX OF GRAPH TRAVERSAL BY DFS ALGORITHM ...var arr = \[   \[0,1,1,1,0],  \[1,0,0,1,1],  \[1,0,0,1,0],  \[1,1,1,0,1],  \[0,1,0,1,0] ];document.write("DFS of the given graph is : ");dfs(arr,0);
Estos cursos están muy mal organizados, uno viene de ver fundamentos de algoritmos y llega aquí y no entiende nada, ella dice que hay un curso antes de este pero no se sabe cual es, deberían hacer una ruta solo de algoritmos que uno sepa cual seguir para no perderse, yo la verdad ya me desmotive y siento que enterré mi plata con platzi
Es un curso avanzado... te recomiendan conocimientos previos de estructura de datos y que comprendas sintaxis de dos lenguajes de programación... en mi caso solo se python, Eh disfrutado mucho el curso, tu disgusto es:
te falta practica haciendo estructura de datos.
Ser auto solvente con las herramientas de internet para aprender.
No quedarte solo con el video hay libros, videos y chat gpt3 que te pueden ayudar.
en mi perspectiva el curso esta a nivel de pregrado, y esta diseñado para desarrollar un pensamiento algorítmico (te enseña a pensar) si te cuesta es por que no has aprendido a pensar algorítmicamente por lo cual creo que puedes tomar cursos menos difíciles