Introducción

1

Grafos y Árboles: Estructuras de Datos Avanzadas

2

Estructuras de Datos: Introducción a Árboles y Sus Propiedades

3

Recursión: Concepto y Aplicaciones Prácticas con Ejemplos

4

Aplicaciones Prácticas de Grafos en Tecnología e Industria

5

Representación de Grafos: Matriz y Lista de Adyacencia

DFS

6

Búsqueda en Profundidad (DFS) en Árboles y Grafos

7

Implementación de DFS recursivo para búsqueda en árboles

8

Búsqueda en Profundidad (DFS) para Grafos: Enfoque Iterativo y Recursivo

9

Recorridos y Profundidad en Árboles Binarios y Enearios

10

Suma de Caminos en Árboles Binarios

11

Suma de Números de Raíz a Hoja en Árboles

12

Playground: Sum Root to Leaf Numbers

13

Implementación de Algoritmo DFS en Árboles Binarios con Golang

14

Resolución del Problema de Número de Islas con DFS

15

Conteo de Islas en Matrices con DFS

16

Playground: Number of Islands

17

Implementación de "Número de Islas" con Recursión en Python

18

Ejercicios Prácticos de Búsqueda en Profundidad (DFS)

19

Algoritmos de Búsqueda en Profundidad (DFS) en Problemas Comunes

BFS

20

Algoritmo BFS: Recorrido en Anchura de Grafos y Árboles

21

Implementación de BFS en Árboles usando Python

22

Movimiento mínimo de caballo en ajedrez infinito

23

Resolviendo el Problema Mínimo de Movimiento del Caballo en Ajedrez

24

Playground: Minimum Knights Moves

25

Resolución de Problemas de Caballos de Ajedrez con BFS en Python

26

Propagación de Plagas en Cultivos: Cálculo de Días para Contagio Total

27

Resolución de Rotting Oranges usando BFS

28

Playground: Rotting Oranges

29

Propagación de Plagas en Matrices usando BFS en Java

30

Construcción de Puentes Cortos entre Islas en Matrices Binarias

31

Resolución del Problema Shortest Bridge con DFS y BFS

32

Playground: Shortest Bridge Between Islands

33

Búsqueda del camino más corto entre islas usando BFS en Python

34

Búsqueda en anchura: Ejercicios prácticos y aplicaciones

35

Ejercicios avanzados de búsqueda en anchura (BFS) en programación

Backtrack

36

Algoritmo Backtracking: Solución de Problemas Complejos

37

Combinaciones de Letras en Números Telefónicos

38

Combinaciones de Letras a partir de un Número de Teléfono

39

Generación de combinaciones de letras con teclados numéricos en C++

40

Playground: Letter Combinations of a Phone Number

41

Generación de Direcciones IP Válidas a partir de Cadenas Numéricas

42

Generación de IPs válidas con backtracking en C++

43

Playground: Restore IP Addresses

44

Búsqueda de Palabras en Matrices: Solución y Complejidad

45

Búsqueda de Palabras en Matrices usando Backtracking y DFS

46

Playgrund: Word Search

47

Implementación de búsqueda de palabras en matrices con DFS en JavaScript

48

Resolución del problema de las n reinas en ajedrez

49

Ejercicios de Backtracking: Combinaciones y Permutaciones

50

Combinaciones y Permutaciones con Backtracking

Próximos pasos

51

Algoritmos de Grafos: MIN/MAX-HIP, TRI, Topological Sort y Dijkstra

52

Algoritmos y Estructuras de Datos en la Ingeniería

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Implementación de DFS recursivo para búsqueda en árboles

7/52
Recursos

¿Cómo implementar DFS para encontrar un número en un árbol?

La implementación de algoritmos se vuelve una tarea más compleja sin un objetivo claro. En esta clase, aprenderás a implementar el algoritmo Depth First Search (DFS) para encontrar un número en un árbol, paso a paso, utilizando JavaScript. Este enfoque podrá aplicarse a cualquier lenguaje de programación y ajustarse a tus necesidades específicas.

¿Cómo se determina el objetivo del algoritmo?

Antes de sumergirse en la implementación, es crucial definir un objetivo específico para el algoritmo. En este caso, la meta será encontrar un número en un árbol. La función que se desarrollará tomará dos argumentos principales: la raíz del árbol y el valor que queremos localizar.

¿Cómo funcionan las bases del algoritmo DFS?

La base del algoritmo DFS recursivo se centra en dos elementos cruciales:

  • Caso base: Define cuándo el proceso termina exitosamente, es decir, cuando encuentra el nodo que contiene el valor buscado.
  • Recursión: Si no se encuentra el valor en el nodo actual, DFS profundiza revisando los hijos de ese nodo.

En caso de no localizar el nodo deseado durante la exploración, el algoritmo devuelve un resultado nulo, indicando que el valor no está presente en ese camino específico.

¿Cómo se implementa recursivamente en JavaScript?

A continuación, se presenta una implementación de DFS en JavaScript para encontrar un número en un árbol. Esta versión recursiva puede ser la base para desarrollos más complejos adaptados a diferentes estructuras de datos.

function DFS(root, targetValue) {
    console.log(`Actualmente estoy en el nodo con valor: ${root.valor}`);
    
    if (root.valor === targetValue) {
        console.log(`¡Encontré el valor ${targetValue}!`);
        return root;
    }
    
    for (let i = 0; i < root.children.length; i++) {
        const childNode = root.children[i];
        const resultNode = DFS(childNode, targetValue);
        if (resultNode !== null) {
            return resultNode;
        }
    }
    
    return null;
}

¿Cómo se adapta DFS a un árbol binario?

En un árbol binario, cada nodo tiene un máximo de dos hijos, por lo que la función simplifica la iteración sobre los hijos a dos opciones: izquierda y derecha. Aquí está un ejemplo de cómo se adapta el código para un árbol binario:

function DFSBinary(root, targetValue) {
    if (root === null) return null;
    
    console.log(`Actualmente estoy en el nodo con valor: ${root.valor}`);
    
    if (root.valor === targetValue) {
        console.log(`¡Encontré el valor ${targetValue}!`);
        return root;
    }
    
    const leftResult = DFSBinary(root.izquierda, targetValue);
    if (leftResult !== null) {
        return leftResult;
    }
    
    const rightResult = DFSBinary(root.derecha, targetValue);
    if (rightResult !== null) {
        return rightResult;
    }
    
    return null;
}

¿Cuál es la importancia de DFS?

DFS es crucial en la exploración exhaustiva de estructuras de datos jerárquicas, permitiendo alcanzar nodos profundos y detectar todos los posibles caminos desde un nodo raíz. Es comúnmente utilizado en problemas de grafos y es una técnica fundamental en algoritmos de búsqueda y recorridos de árboles.

¿Qué otras formas de implementación existen?

DFS puede ser implementado de manera iterativa, usando una estructura de datos llamada pila (stack). Este enfoque alternativo evita el uso extensivo de la pila del sistema operativo, que se utiliza en la recursión y puede agotarse en árboles muy profundos. La iterativa es una implementación robusta para árboles de gran tamaño.

¡Sigue practicando y explorando más formas de implementar y adaptar DFS a diferentes problemas! La comprensión y habilidad técnica mejorarán al experimentar con estos conceptos en diversos contextos.

Aportes 14

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

A este punto sería bueno hacer un ejemplo práctica para entender mejor el tema.

Hola 😄, pueden probar el código con el siguiente árbol de ejemplo.
.

.
dfsBin.js:

const dfs = function (raiz, valorAEncontrar) {
  if (!raiz) {
    // si raiz es null o undefined, termina la función
    return null;
  }

  console.log("En este momento estoy en el nodo, el valor " + raiz.valor);
  if (raiz.valor === valorAEncontrar) {
    console.log("Econtré el valor!!! ");
    return raiz;
  }

  var izquierda = dfs(raiz.izquierda, valorAEncontrar);
  var derecha = dfs(raiz.derecha, valorAEncontrar);
  if (izquierda != null) {
    return izquierda;
  }
  if (derecha != null) {
    return derecha;
  }

  return null;
};

//Creación del árbol como objeto
let nodos = {
  valor: 25,
  izquierda: {
    valor: 10,
    izquierda: {
      valor: 8,
      izquierda: {
        valor: 6,
        izquierda: {
          valor: 1,
          izquierda: null,
          derecha: null,
        },
        derecha: {
          valor: 7,
          izquierda: null,
          derecha: null,
        },
      },
      derecha: null,
    },
    derecha: {
      valor: 13,
      izquierda: null,
      derecha: {
        valor: 15,
        izquierda: null,
        derecha: null,
      },
    },
  },
  derecha: {
    valor: 40,
    izquierda: {
      valor: 30,
      izquierda: {
        valor: 26,
        izquierda: null,
        derecha: null,
      },
      derecha: null,
    },
    derecha: {
      valor: 42,
      izquierda: null,
      derecha: {
        valor: 49,
        izquierda: {
          valor: 45,
          izquierda: null,
          derecha: null,
        },
        derecha: {
          valor: 51,
          izquierda: null,
          derecha: null,
        },
      },
    },
  },
};

// Probar la función dfs
let nodoEncontrado = dfs(nodos, 30);
console.log("\nEl valor encontrado es:\n");
console.log(nodoEncontrado);

.
Pueden ejecutarlo por la terminal, desde el directorio donde tienen guardado el archivo, ejecutando:

node dfsBin.js
así sería el recorrido en alrbol binario, a la izquierda BFS y a la derecha DFS ![](https://static.platzi.com/media/user_upload/image-50b4ea0f-6c0f-49e3-80b9-68822b52e9d1.jpg)

Seria bueno en este caso, mostrar como es el objeto que se va a recorrer con eso queda un poco ilulstrado

este algoritmo tal cual está implementado terminará lanzando un error en el caso que el valor objetivo no esté dentro del grafo. Es tan importante definir el caso bueno (valor encontrado) como el malo (valor no encontrado). Se puede validar tanto si "raiz" es null, como "raiz.left" y "raiz.right" son null (prefiero esta segunda opción). . Además creo que el uso del término "raiz" es incorrecto/confuso, ya que la raiz hace referencia al nodo raiz del grafo. Aunque podemos debatir sobre si consideramos cada iteración un subgrafo (por lo que raiz sería correcto), creo que es mejor llamarlo "padre".

Estaria bueno primero tener un video de como es la estructura de una grafo, como se implementa, que propiedades y metodos tiene para entender mejor el algoritmo

![](https://static.platzi.com/media/user_upload/image-1adf3168-74e2-4c51-a6e1-aaccee4f4d5d.jpg) ![](https://static.platzi.com/media/user_upload/image-d000bd23-fdc1-45a2-88c9-5d5f83638da3.jpg) ![](https://static.platzi.com/media/user_upload/image-ebf37b3b-202f-4ee2-94db-59b640390537.jpg)
Hola! Para los que andan perdidos como yo lo estaba. Aquí les traigo un ejemplo de como sería este código (con unas mejoras), para un grafo con la representación **Lista de adyacencia.** **Este es mi grafo y en azul está el recorrido que hace el algoritmo:** ![](https://static.platzi.com/media/user_upload/Screenshot_20250326_164252_touchnotes-1ccf113b-554c-4190-9dcd-240a57b5e488.jpg) ![](https://static.platzi.com/media/user_upload/image-25ef7ec4-a424-47d2-9cb0-9f39a2b5218c.jpg) ```python class Graph: def __init__(self): self.adj_list = {} def add_edge(self, u, v): if u not in self.adj_list: self.adj_list[u] = [] if v not in self.adj_list: self.adj_list[v] = [] self.adj_list[u].append(v) self.adj_list[v].append(u) ``````python def dfs_recursive_search(adj_list, nodo, valorAEncontrar, visitado=None): if visitado is None: visitado = set() # Inicializa el conjunto de nodos visitados print(f'Estamos en el nodo con el valor: {nodo}') if nodo == valorAEncontrar: print('Hemos encontrado el valor :)') return nodo visitado.add(nodo) # Marca el nodo como visitado for hijo in adj_list.get(nodo, []): # Itera sobre los vecinos del nodo if hijo not in visitado: nodoResultado = dfs_recursive_search(adj_list, hijo, valorAEncontrar, visitado) if nodoResultado: return nodoResultado # Si lo encuentra, lo devuelve return None # Si no lo encontró en ningún camino ```
Mi version en C++ incluyendo creando el arbol con linked lists ```txt //Depth First Search #include<iostream> using namespace std; class Node{ public: int value; Node *leftNode = NULL; Node *rightNode = NULL; Node(int value, Node *leftNode, Node *rightNode){ this->value = value; this->leftNode = leftNode; this->rightNode= rightNode; } }; Node *dfs(Node *root, int targetVal){ if(root != NULL && root->value == targetVal){ return root; } Node *leftNode; Node *rightNode; if(root->leftNode) leftNode = dfs(root->leftNode, targetVal); if(root->rightNode) rightNode = dfs(root->rightNode, targetVal); if(leftNode) return leftNode; if(rightNode) return rightNode; return NULL; } Node *recursiveFill(Node *node, int value){ if(value < 15){ node->leftNode = recursiveFill(new Node(value, NULL, NULL), value+1); node->rightNode = recursiveFill(new Node(value+2, NULL, NULL), value+3); } return node; } int main(){ Node *binaryTree = recursiveFill(new Node(0, NULL, NULL), 1); cout << binaryTree->value << endl; Node *foundNode = dfs(binaryTree, 6); if(foundNode) cout << "found: " << foundNode->value << endl; delete binaryTree; return 0; } ```
Es de los cursos con menos comentarios que he visto y es de los temas mas importantes, pero uno no se da cuenta de eso hasta que deja de intentar de aprender los 100 lenguajes que existen y se da cuenta que solo hay que aprender las bases y la sintaxis no es tan importante, que paradoja
Siguiendo el ejemplo de un arbol con valores númericos me aborde a implementar DFS en go (dado que es un lenguaje que estoy aprendiendo), así que les comparto el codigo que realice (blob:https://app.codeimage.dev/30f31b71-b4b5-4414-af95-195c11d9b256). ![](https://static.platzi.com/media/user_upload/image-69fabf28-dba8-47ca-a539-6e8e25aadfcc.jpg)
hice este código en java creando la clase Nodo\<T> donde se pueden agregar los hijos en una lista, su valor y el valor del padre (por si acaso xd) ```java public class DFS { public static void main(String[] args) { System.out.println("********** DFS ***********"); Nodo<Integer> head = prepareHead(); System.out.println("ingrese el valor del nodo a buscar"); Scanner sc = new Scanner(System.in); int valorABuscar = sc.nextInt(); System.out.printf("valor [%s] encontrado: %b\n", valorABuscar, buscarNodo(head, valorABuscar) != null); } private static Nodo<Integer> buscarNodo(Nodo<Integer> head, int valorABuscar) { System.out.printf("buscando valor [%d] en nodo con valor [%d]\n", valorABuscar, head.valor); if(head.valor == valorABuscar){ return head; } if(head.hijos != null) { for (Nodo<Integer> hijo : head.hijos) { Nodo<Integer> resultado = buscarNodo(hijo, valorABuscar); if (resultado != null && resultado.valor.equals(valorABuscar)) { return resultado; } } } return null; } private static Nodo<Integer> prepareHead() { Nodo<Integer> cabeza = new Nodo<>(1); Nodo<Integer> hijo1 = new Nodo<>(2, cabeza); Nodo<Integer> hijo2 = new Nodo<>(3, cabeza); Nodo<Integer> hijo3 = new Nodo<>(4, cabeza); cabeza.hijos = (Arrays.asList(hijo1, hijo2, hijo3)); Nodo<Integer> nieto1 = new Nodo<>(5, hijo1); Nodo<Integer> nieto2 = new Nodo<>(6, hijo1); Nodo<Integer> nieto3 = new Nodo<>(7, hijo1); hijo1.hijos = (Arrays.asList(nieto1, nieto2, nieto3)); Nodo<Integer> nieto4 = new Nodo<>(8, hijo2); Nodo<Integer> nieto5 = new Nodo<>(9, hijo2); Nodo<Integer> nieto6 = new Nodo<>(10, hijo2); hijo2.hijos = (Arrays.asList(nieto4, nieto5, nieto6)); Nodo<Integer> nieto7 = new Nodo<>(11, hijo3); Nodo<Integer> nieto8 = new Nodo<>(12, hijo3); Nodo<Integer> nieto9 = new Nodo<>(13, hijo3); hijo3.hijos = (Arrays.asList(nieto7, nieto8, nieto9)); return cabeza; } static class Nodo<T> { T valor; Nodo<T> padre; List<Nodo<T>> hijos; public Nodo(T valor) { this.valor = valor; } public Nodo(T valor, Nodo<T> padre) { this.valor = valor; this.padre = padre; } } } ```
tengo un poco de dudas de como implemetar el nodo en JS porque no es mi fuerte, pero esa es la idea porque en Jav sin problamas ya lo implemete: ![](https://static.platzi.com/media/user_upload/image-a5dd6816-e65a-44b9-a43c-3cfb3e2ce097.jpg) Este es el link de l repo(https://github.com/Dani-Ideas/DFS\_JS)
# Función para realizar DFS en un grafo dado
def dfs(graph, node, visited):
    # Marcar el nodo actual como visitado
    visited[node] = True
    print("Visitando nodo:", node)

    # Recorrer todos los nodos adyacentes al nodo actual
    for neighbor in graph[node]:
        if not visited[neighbor]:
            # Si el vecino no ha sido visitado, realizar DFS en él
            dfs(graph, neighbor, visited)


# Ejemplo de uso
if __name__ == "__main__":
    # Grafo representado como listas de adyacencia
    graph = {
        0: [1, 2],
        1: [0, 3, 4],
        2: [0, 5],
        3: [1],
        4: [1],
        5: [2]
    }

    # Inicializar un arreglo para llevar un seguimiento de los nodos visitados
    visited = [False] * len(graph)

    # Realizar DFS desde el nodo 0
    dfs(graph, 0, visited)