🌳 ¿Qué es la exploración de árboles?
Los árboles son una de las estructuras de datos no lineales más importantes en ciencias de la computación. Se utilizan para representar jerarquías, organizar datos de búsqueda y modelar decisiones. Sin embargo, una estructura de datos solo resulta útil si podemos acceder a sus elementos de forma sistemática. A este proceso de visitar todos los nodos de un árbol siguiendo un orden determinado se le denomina exploración o recorrido de árboles (tree traversal).
A diferencia de las estructuras lineales como arrays o listas enlazadas, donde existe un único camino natural para recorrer los elementos, en un árbol existen múltiples formas válidas de visitar todos los nodos. Cada estrategia de recorrido produce un orden diferente de visita y tiene aplicaciones específicas en algoritmia.
Los recorridos de árboles se clasifican en dos grandes familias:
✅ Recorridos en profundidad (Depth-First Search, DFS): exploran la mayor profundidad posible en cada rama antes de retroceder. Se implementan naturalmente con recursión. Dentro de esta familia encontramos tres variantes: preorden, inorden y postorden.
✅ Recorridos en anchura (Breadth-First Search, BFS): exploran nivel por nivel, visitando todos los nodos de una misma profundidad antes de descender al siguiente nivel. Utilizan una cola como estructura auxiliar.
📜 Contexto histórico: Knuth y los recorridos de árboles
Los algoritmos de recorrido de árboles tienen raíces profundas en la historia de las ciencias de la computación. Donald E. Knuth, profesor emérito de Stanford y autor de la monumental obra The Art of Computer Programming, fue uno de los primeros en formalizar y sistematizar los algoritmos de recorrido de árboles binarios en el volumen 1 de su serie, publicado en 1968.
Knuth planteó un problema fundamental que ocupó a los informáticos durante décadas: diseñar un algoritmo que recorriese un árbol binario en inorden sin usar recursión ni una pila auxiliar. Este desafío inspiró soluciones elegantes como el algoritmo de Morris (1979), que utiliza los punteros nulos del propio árbol para crear enlaces temporales (threaded tree), logrando un recorrido inorden con complejidad espacial O(1).
La notación que usamos hoy — preorden, inorden y postorden — se consolidó precisamente en los trabajos de Knuth y fue adoptada universalmente en la enseñanza de estructuras de datos. Comprender estos recorridos es fundamental para cualquier programador, ya que aparecen en compiladores, bases de datos, sistemas de archivos, inteligencia artificial y muchos otros dominios.
🧱 Estructura de un nodo de árbol binario en Java
Antes de implementar los recorridos, necesitamos definir la estructura básica de un nodo de árbol binario. Cada nodo almacena un dato y referencias a sus hijos izquierdo y derecho. En Java, modelamos esta estructura con una clase genérica:
public class NodoArbol<T> {
T dato;
NodoArbol<T> izquierdo;
NodoArbol<T> derecho;
public NodoArbol(T dato) {
this.dato = dato;
this.izquierdo = null;
this.derecho = null;
}
public NodoArbol(T dato, NodoArbol<T> izquierdo, NodoArbol<T> derecho) {
this.dato = dato;
this.izquierdo = izquierdo;
this.derecho = derecho;
}
@Override
public String toString() {
return dato.toString();
}
}
Con esta clase podemos construir cualquier árbol binario enlazando nodos. Por ejemplo, el siguiente código crea un árbol de prueba que usaremos a lo largo de todo el artículo:
/*
* Árbol de ejemplo:
*
* a
* / \
* b c
* / \
* d e
*/
NodoArbol<String> d = new NodoArbol<>("d");
NodoArbol<String> e = new NodoArbol<>("e");
NodoArbol<String> b = new NodoArbol<>("b", d, e);
NodoArbol<String> c = new NodoArbol<>("c");
NodoArbol<String> a = new NodoArbol<>("a", b, c);
// 'a' es la raíz del árbol
<T>) permite que el árbol almacene cualquier tipo de dato (String, Integer, objetos propios), manteniendo la seguridad de tipos en tiempo de compilación.🔍 Recorridos en profundidad (DFS)
Los recorridos en profundidad (Depth-First Search) se caracterizan por explorar completamente cada rama del árbol antes de pasar a la siguiente. Se implementan de forma natural mediante recursión, aprovechando la propia estructura recursiva del árbol: un árbol es un nodo raíz con subárboles izquierdo y derecho, cada uno de los cuales es a su vez un árbol.
Las tres variantes de DFS se diferencian únicamente en cuándo se procesa la raíz respecto a los subárboles:
| Recorrido | Orden de visita | Mnemotécnico |
|---|---|---|
| Preorden | Raíz → Izquierdo → Derecho | RID — la Raíz va primero |
| Inorden | Izquierdo → Raíz → Derecho | IRD — la Raíz va en medio |
| Postorden | Izquierdo → Derecho → Raíz | IDR — la Raíz va al final |
▶️ Recorrido en preorden (Pre-order)
En el recorrido en preorden, se visita primero la raíz, después el subárbol izquierdo y finalmente el subárbol derecho. Es el recorrido más intuitivo y el que refleja la estructura del árbol de forma más directa.
🔹 Algoritmo paso a paso
El algoritmo consta de tres pasos para cada nodo:
1. Procesar el nodo actual (por ejemplo, imprimir su valor).
2. Llamar recursivamente al método con el hijo izquierdo.
3. Llamar recursivamente al método con el hijo derecho.
/**
* Recorrido en preorden: Raíz → Izquierdo → Derecho
* @param nodo raíz del subárbol a recorrer
*/
public static <T> void preorden(NodoArbol<T> nodo) {
if (nodo == null) {
return; // Caso base: subárbol vacío
}
System.out.print(nodo.dato + " "); // 1. Procesar raíz
preorden(nodo.izquierdo); // 2. Recorrer subárbol izquierdo
preorden(nodo.derecho); // 3. Recorrer subárbol derecho
}
🔹 Traza del ejemplo
Aplicando preorden al árbol de ejemplo (raíz a):
preorden(a) → imprime "a", luego preorden(b), luego preorden(c)
preorden(b) → imprime "b", luego preorden(d), luego preorden(e)
preorden(d) → imprime "d", luego preorden(null), preorden(null) → retorna
preorden(e) → imprime "e", luego preorden(null), preorden(null) → retorna
preorden(c) → imprime "c", luego preorden(null), preorden(null) → retorna
Resultado: a b d e c
🔀 Recorrido en inorden (In-order)
En el recorrido en inorden, se visita primero el subárbol izquierdo, después la raíz y finalmente el subárbol derecho. Este recorrido tiene una propiedad fundamental: cuando se aplica a un árbol binario de búsqueda (BST), los nodos se visitan en orden ascendente.
/**
* Recorrido en inorden: Izquierdo → Raíz → Derecho
* En un BST, produce los valores en orden ascendente.
* @param nodo raíz del subárbol a recorrer
*/
public static <T> void inorden(NodoArbol<T> nodo) {
if (nodo == null) {
return;
}
inorden(nodo.izquierdo); // 1. Recorrer subárbol izquierdo
System.out.print(nodo.dato + " "); // 2. Procesar raíz
inorden(nodo.derecho); // 3. Recorrer subárbol derecho
}
🔹 Traza del ejemplo
inorden(a) → inorden(b), imprime "a", inorden(c)
inorden(b) → inorden(d), imprime "b", inorden(e)
inorden(d) → inorden(null), imprime "d", inorden(null)
inorden(e) → inorden(null), imprime "e", inorden(null)
inorden(c) → inorden(null), imprime "c", inorden(null)
Resultado: d b e a c
🔹 Inorden en un BST numérico
Observa cómo el inorden produce los valores ordenados en un BST:
/* * BST numérico: * 8 * / \ * 3 10 * / \ \ * 1 6 14 */ NodoArbol<Integer> n1 = new NodoArbol<>(1); NodoArbol<Integer> n6 = new NodoArbol<>(6); NodoArbol<Integer> n14 = new NodoArbol<>(14); NodoArbol<Integer> n3 = new NodoArbol<>(3, n1, n6); NodoArbol<Integer> n10 = new NodoArbol<>(10, null, n14); NodoArbol<Integer> n8 = new NodoArbol<>(8, n3, n10); inorden(n8); // Salida: 1 3 6 8 10 14 (¡ordenados!)
🔄 Recorrido en postorden (Post-order)
En el recorrido en postorden, se visitan primero ambos subárboles y la raíz se procesa al final. Este recorrido es particularmente útil cuando necesitamos procesar los hijos antes que el padre, como al calcular el tamaño de directorios o al liberar la memoria de un árbol.
/**
* Recorrido en postorden: Izquierdo → Derecho → Raíz
* Ideal para liberar memoria o calcular propiedades bottom-up.
* @param nodo raíz del subárbol a recorrer
*/
public static <T> void postorden(NodoArbol<T> nodo) {
if (nodo == null) {
return;
}
postorden(nodo.izquierdo); // 1. Recorrer subárbol izquierdo
postorden(nodo.derecho); // 2. Recorrer subárbol derecho
System.out.print(nodo.dato + " "); // 3. Procesar raíz
}
🔹 Traza del ejemplo
postorden(a) → postorden(b), postorden(c), imprime "a"
postorden(b) → postorden(d), postorden(e), imprime "b"
postorden(d) → postorden(null), postorden(null), imprime "d"
postorden(e) → postorden(null), postorden(null), imprime "e"
postorden(c) → postorden(null), postorden(null), imprime "c"
Resultado: d e b c a
🔹 Aplicación: calcular la altura del árbol
El postorden es la estrategia natural para calcular propiedades bottom-up (de las hojas hacia la raíz), como la altura:
/**
* Calcula la altura de un árbol binario usando recorrido postorden.
* La altura de un árbol vacío es -1 por convención.
*/
public static <T> int altura(NodoArbol<T> nodo) {
if (nodo == null) {
return -1; // Caso base
}
int alturaIzq = altura(nodo.izquierdo); // Postorden: primero hijos
int alturaDer = altura(nodo.derecho);
return 1 + Math.max(alturaIzq, alturaDer); // Después raíz
}
// Ejemplo:
System.out.println(altura(a)); // Salida: 2 (a→b→d tiene 2 aristas)
🌊 Recorrido en anchura (BFS — Breadth-First Search)
A diferencia de los recorridos en profundidad, el recorrido en anchura explora el árbol nivel por nivel, visitando todos los nodos de una misma profundidad antes de pasar al siguiente nivel. Es el equivalente a leer un libro «de izquierda a derecha y de arriba abajo».
La implementación utiliza una cola (Queue) como estructura auxiliar. El algoritmo funciona de la siguiente manera:
1. Insertar la raíz en la cola.
2. Mientras la cola no esté vacía, extraer el nodo del frente.
3. Procesar el nodo extraído.
4. Insertar en la cola los hijos del nodo (primero izquierdo, luego derecho), si existen.
import java.util.LinkedList;
import java.util.Queue;
/**
* Recorrido en anchura (BFS): nivel por nivel, de izquierda a derecha.
* Usa una cola FIFO como estructura auxiliar.
* @param raiz nodo raíz del árbol
*/
public static <T> void bfs(NodoArbol<T> raiz) {
if (raiz == null) {
return;
}
Queue<NodoArbol<T>> cola = new LinkedList<>();
cola.add(raiz); // 1. Insertar raíz
while (!cola.isEmpty()) {
NodoArbol<T> actual = cola.poll(); // 2. Extraer del frente
System.out.print(actual.dato + " "); // 3. Procesar
if (actual.izquierdo != null) {
cola.add(actual.izquierdo); // 4a. Encolar hijo izquierdo
}
if (actual.derecho != null) {
cola.add(actual.derecho); // 4b. Encolar hijo derecho
}
}
}
🔹 Traza paso a paso
Cola inicial: [a] Paso 1: Extraer a → Procesar "a" → Encolar b, c → Cola: [b, c] Paso 2: Extraer b → Procesar "b" → Encolar d, e → Cola: [c, d, e] Paso 3: Extraer c → Procesar "c" → Sin hijos → Cola: [d, e] Paso 4: Extraer d → Procesar "d" → Sin hijos → Cola: [e] Paso 5: Extraer e → Procesar "e" → Sin hijos → Cola: [] Resultado: a b c d e (nivel 0, nivel 1, nivel 2)
🔹 BFS por niveles (con separación)
Una variante muy utilizada es el recorrido por niveles (level-order traversal), que agrupa los nodos por profundidad. Esto es muy útil para imprimir el árbol visualmente o para algoritmos que necesitan procesar cada nivel de forma independiente:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
/**
* Recorrido BFS por niveles. Devuelve una lista de listas,
* donde cada sublista contiene los valores de un nivel del árbol.
*/
public static <T> List<List<T>> bfsPorNiveles(NodoArbol<T> raiz) {
List<List<T>> niveles = new ArrayList<>();
if (raiz == null) {
return niveles;
}
Queue<NodoArbol<T>> cola = new LinkedList<>();
cola.add(raiz);
while (!cola.isEmpty()) {
int tamanoNivel = cola.size(); // Nodos en el nivel actual
List<T> nivelActual = new ArrayList<>();
for (int i = 0; i < tamanoNivel; i++) {
NodoArbol<T> nodo = cola.poll();
nivelActual.add(nodo.dato);
if (nodo.izquierdo != null) cola.add(nodo.izquierdo);
if (nodo.derecho != null) cola.add(nodo.derecho);
}
niveles.add(nivelActual);
}
return niveles;
}
// Ejemplo de uso:
// bfsPorNiveles(a) → [[a], [b, c], [d, e]]
cola.size() al inicio de cada iteración. Ese valor nos indica cuántos nodos pertenecen al nivel actual, ya que todos los nodos encolados durante la iteración pertenecerán al nivel siguiente.⚖️ Comparativa DFS vs BFS
Elegir entre DFS y BFS depende del problema concreto, la forma del árbol y los requisitos de memoria. A continuación se presenta una comparativa detallada:
| Criterio | DFS (Profundidad) | BFS (Anchura) |
|---|---|---|
| Estructura auxiliar | Pila (implícita o explícita) | Cola (Queue) |
| Complejidad temporal | O(n) | O(n) |
| Complejidad espacial | O(h) donde h = altura | O(w) donde w = anchura máxima |
| Mejor para árboles... | Profundos y estrechos | Anchos y poco profundos |
| Encuentra camino más corto | ❌ No garantizado | ✅ Sí (en grafos no ponderados) |
| Implementación natural | Recursión | Iterativa con cola |
| Riesgo de Stack Overflow | ⚠️ En árboles muy profundos | ❌ No aplica |
| Uso típico | Búsqueda, serialización, cálculos bottom-up | Encontrar nodo más cercano, recorrido por niveles |
StackOverflowError. En esos casos, usa la versión iterativa con pila explícita que veremos más adelante.📚 DFS iterativo con pila explícita
Aunque la recursión es la forma más natural de implementar DFS, en ciertos escenarios — árboles extremadamente profundos o entornos con pila de llamadas limitada — conviene usar una pila explícita. Esto nos da el mismo resultado que la versión recursiva pero sin riesgo de desbordamiento de pila.
🔹 Preorden iterativo
import java.util.ArrayDeque;
import java.util.Deque;
/**
* Recorrido en preorden usando pila explícita (iterativo).
* Evita StackOverflowError en árboles muy profundos.
*/
public static <T> void preordenIterativo(NodoArbol<T> raiz) {
if (raiz == null) {
return;
}
Deque<NodoArbol<T>> pila = new ArrayDeque<>();
pila.push(raiz);
while (!pila.isEmpty()) {
NodoArbol<T> actual = pila.pop();
System.out.print(actual.dato + " ");
// Apilar derecho primero para que izquierdo salga antes (LIFO)
if (actual.derecho != null) {
pila.push(actual.derecho);
}
if (actual.izquierdo != null) {
pila.push(actual.izquierdo);
}
}
}
// preordenIterativo(a) → a b d e c (mismo resultado que recursivo)
🔹 Inorden iterativo
El inorden iterativo es ligeramente más complejo. Necesitamos ir bajando por la izquierda hasta llegar a null, procesar el nodo y luego movernos al subárbol derecho:
/**
* Recorrido en inorden usando pila explícita (iterativo).
*/
public static <T> void inordenIterativo(NodoArbol<T> raiz) {
Deque<NodoArbol<T>> pila = new ArrayDeque<>();
NodoArbol<T> actual = raiz;
while (actual != null || !pila.isEmpty()) {
// Descender por la izquierda hasta el fondo
while (actual != null) {
pila.push(actual);
actual = actual.izquierdo;
}
// Procesar el nodo del tope de la pila
actual = pila.pop();
System.out.print(actual.dato + " ");
// Moverse al subárbol derecho
actual = actual.derecho;
}
}
// inordenIterativo(a) → d b e a c (mismo resultado que recursivo)
🏗️ Ejemplo integrador: explorador de sistema de archivos
Para integrar todos los conceptos, implementaremos un sistema de archivos simulado representado como un árbol. Cada nodo puede ser un directorio (con hijos) o un archivo (hoja). Aplicaremos los diferentes recorridos para resolver problemas reales: listar archivos, calcular tamaños y buscar elementos.
import java.util.*;
/**
* Nodo del sistema de archivos. Puede ser archivo o directorio.
* Los directorios pueden tener múltiples hijos (árbol n-ario).
*/
class NodoFS {
String nombre;
boolean esDirectorio;
long tamanoBytes; // Solo para archivos
List<NodoFS> hijos; // Solo para directorios
// Constructor para archivo
NodoFS(String nombre, long tamanoBytes) {
this.nombre = nombre;
this.esDirectorio = false;
this.tamanoBytes = tamanoBytes;
this.hijos = Collections.emptyList();
}
// Constructor para directorio
NodoFS(String nombre, NodoFS... hijos) {
this.nombre = nombre;
this.esDirectorio = true;
this.tamanoBytes = 0;
this.hijos = Arrays.asList(hijos);
}
}
public class ExploradorFS {
/**
* PREORDEN: Listar todos los elementos con indentación.
* Procesa la raíz primero → muestra la estructura jerárquica.
*/
public static void listarArbol(NodoFS nodo, int profundidad) {
if (nodo == null) return;
String indent = " ".repeat(profundidad);
String icono = nodo.esDirectorio ? "📁" : "📄";
String info = nodo.esDirectorio ? "" : " (" + nodo.tamanoBytes + " bytes)";
System.out.println(indent + icono + " " + nodo.nombre + info);
for (NodoFS hijo : nodo.hijos) {
listarArbol(hijo, profundidad + 1);
}
}
/**
* POSTORDEN: Calcular el tamaño total de un directorio.
* Procesa los hijos primero → suma sus tamaños antes de reportar.
*/
public static long calcularTamano(NodoFS nodo) {
if (nodo == null) return 0;
if (!nodo.esDirectorio) {
return nodo.tamanoBytes; // Archivo: retornar su tamaño
}
long total = 0;
for (NodoFS hijo : nodo.hijos) {
total += calcularTamano(hijo); // Postorden: hijos primero
}
return total; // Luego la raíz acumula
}
/**
* BFS: Encontrar el archivo más grande en el primer nivel.
* Explora nivel por nivel → ideal para búsquedas de proximidad.
*/
public static String archivoMasGrandeNivel(NodoFS raiz, int nivelObjetivo) {
if (raiz == null) return null;
Queue<NodoFS> cola = new LinkedList<>();
cola.add(raiz);
int nivelActual = 0;
String mayorArchivo = null;
long mayorTamano = -1;
while (!cola.isEmpty() && nivelActual <= nivelObjetivo) {
int tamNivel = cola.size();
for (int i = 0; i < tamNivel; i++) {
NodoFS nodo = cola.poll();
if (nivelActual == nivelObjetivo && !nodo.esDirectorio) {
if (nodo.tamanoBytes > mayorTamano) {
mayorTamano = nodo.tamanoBytes;
mayorArchivo = nodo.nombre;
}
}
for (NodoFS hijo : nodo.hijos) {
cola.add(hijo);
}
}
nivelActual++;
}
return mayorArchivo;
}
public static void main(String[] args) {
// Construir sistema de archivos de ejemplo
NodoFS raiz = new NodoFS("proyecto",
new NodoFS("src",
new NodoFS("Main.java", 2048),
new NodoFS("Utils.java", 1024),
new NodoFS("modelos",
new NodoFS("Usuario.java", 512),
new NodoFS("Producto.java", 768)
)
),
new NodoFS("docs",
new NodoFS("README.md", 4096),
new NodoFS("API.md", 8192)
),
new NodoFS("pom.xml", 256)
);
System.out.println("=== Listado del árbol (Preorden) ===");
listarArbol(raiz, 0);
System.out.println("\n=== Tamaño total (Postorden) ===");
System.out.println("Total: " + calcularTamano(raiz) + " bytes");
System.out.println("\n=== Archivo más grande en nivel 2 (BFS) ===");
System.out.println("Archivo: " + archivoMasGrandeNivel(raiz, 2));
}
}
🔹 Salida esperada
=== Listado del árbol (Preorden) ===
📁 proyecto
📁 src
📄 Main.java (2048 bytes)
📄 Utils.java (1024 bytes)
📁 modelos
📄 Usuario.java (512 bytes)
📄 Producto.java (768 bytes)
📁 docs
📄 README.md (4096 bytes)
📄 API.md (8192 bytes)
📄 pom.xml (256 bytes)
=== Tamaño total (Postorden) ===
Total: 16896 bytes
=== Archivo más grande en nivel 2 (BFS) ===
Archivo: API.md
tree en Linux). Postorden calcula propiedades acumulativas (como du -sh). BFS permite búsquedas por nivel de profundidad.✏️ Ejercicios resueltos
Ejercicio 1: Contar nodos de un árbol binario
Escribe un método recursivo que cuente el número total de nodos de un árbol binario. Utiliza la estructura NodoArbol<T> definida anteriormente.
Ejercicio 2: Verificar si un árbol es simétrico
Escribe un método que determine si un árbol binario es simétrico (es decir, si su mitad izquierda es una imagen especular de la derecha).
Ejercicio 3: Encontrar la profundidad de un nodo específico
Implementa un método que, dado un árbol binario y un valor objetivo, devuelva la profundidad (nivel) del nodo que contiene ese valor, o -1 si no existe.
Ejercicio 4: Recorrido en zigzag (BFS alternante)
Implementa un recorrido por niveles en zigzag: el primer nivel se lee de izquierda a derecha, el segundo de derecha a izquierda, el tercero de izquierda a derecha, y así sucesivamente.
⚠️ Errores comunes y buenas prácticas
🔹 Error 1: Olvidar el caso base en recursión
// ❌ MAL: sin caso base → StackOverflowError
public static void preorden(NodoArbol nodo) {
System.out.print(nodo.dato + " ");
preorden(nodo.izquierdo); // NullPointerException cuando hijo es null
preorden(nodo.derecho);
}
// ✅ BIEN: siempre verificar si el nodo es null
public static void preorden(NodoArbol nodo) {
if (nodo == null) return; // CASO BASE OBLIGATORIO
System.out.print(nodo.dato + " ");
preorden(nodo.izquierdo);
preorden(nodo.derecho);
}
🔹 Error 2: Orden incorrecto al apilar en DFS iterativo
// ❌ MAL: apilar izquierdo antes → recorre primero el derecho pila.push(actual.izquierdo); // Sale segundo (LIFO) pila.push(actual.derecho); // Sale primero // ✅ BIEN: apilar derecho antes para que izquierdo salga primero pila.push(actual.derecho); // Sale segundo pila.push(actual.izquierdo); // Sale primero (LIFO)
🔹 Error 3: Usar Stack en lugar de Deque
La clase java.util.Stack hereda de Vector y está obsoleta. La alternativa moderna recomendada por la documentación oficial de Java es usar Deque implementado con ArrayDeque:
// ❌ OBSOLETO: Stack hereda de Vector (sincronizado innecesariamente) Stack<NodoArbol> pila = new Stack<>(); // ✅ RECOMENDADO: ArrayDeque es más rápido y moderno Deque<NodoArbol> pila = new ArrayDeque<>();
🔹 Error 4: No verificar nulos al encolar hijos en BFS
// ❌ MAL: encolar sin verificar → NullPointerException al extraer cola.add(actual.izquierdo); // Puede ser null cola.add(actual.derecho); // ✅ BIEN: verificar antes de encolar if (actual.izquierdo != null) cola.add(actual.izquierdo); if (actual.derecho != null) cola.add(actual.derecho);
if (nodo == null) return;. Esto protege contra NullPointerException y establece el caso base de la recursión.❓ Preguntas frecuentes sobre Exploración de Árboles en Java
Las dudas más comunes respondidas de forma clara y directa.
💬 Foro de discusión
¿Tienes dudas sobre Exploración de Árboles en Java? Comparte tu pregunta con la comunidad.
Todavía no hay mensajes. ¡Sé el primero en participar!