¿Qué es un Árbol?
Un árbol es una estructura de datos jerárquica que consiste en nodos conectados entre sí mediante relaciones de padre e hijo. Es una de las estructuras más versátiles y fundamentales en programación, utilizada en áreas como bases de datos, inteligencia artificial y algoritmos de búsqueda.
Estructura de un Árbol
Raíz (Root): Es el nodo principal del árbol, donde comienza la estructura. No tiene un nodo padre.
Nodo: Cada elemento del árbol. Puede contener un valor y enlaces a otros nodos.
Hijos (Children): Nodos que están directamente conectados a un nodo padre.
Padre (Parent): Nodo que tiene enlaces hacia nodos hijos.
Hojas (Leaves): Nodos sin hijos.
Altura del Árbol: El número de niveles desde la raíz hasta la hoja más lejana.
Tipos de Árboles
Árbol Binario: Cada nodo puede tener como máximo dos hijos.
Árbol Binario de Búsqueda (BST): Los nodos a la izquierda de un nodo tienen valores menores y los de la derecha, mayores.
Árbol Balanceado: Mantiene su altura lo más pequeña posible, mejorando la eficiencia en búsquedas.
Árbol AVL: Un árbol binario de búsqueda autobalanceado.
Árbol Rojo-Negro: Otro tipo de árbol balanceado utilizado en bases de datos y sistemas.
Árbol General: No tiene restricciones en el número de hijos por nodo.
Operaciones Comunes en Árboles
Inserción: Agregar un nodo al árbol.
Búsqueda: Encontrar un valor específico.
Recorridos:
Inorden: Izquierda → Nodo → Derecha.
Preorden: Nodo → Izquierda → Derecha.
Postorden: Izquierda → Derecha → Nodo.
Eliminación: Remover un nodo y reorganizar el árbol.
Un árbol es una estructura de datos fundamental, flexible y utilizada en una variedad de aplicaciones, desde algoritmos de búsqueda hasta diseño de sistemas. Dominar los árboles y sus variantes te permitirá abordar problemas complejos con mayor eficiencia y organización.
Ejemplos de Árboles en Diferentes Lenguajes
JavaScript
En JavaScript, podemos implementar un árbol binario de búsqueda con clases.
class Nodo {
constructor(dato) {
this.dato = dato;
this.izquierda = null;
this.derecha = null;
}
}
class ArbolBinario {
constructor() {
this.raiz = null;
}
insertar(dato) {
const nuevoNodo = new Nodo(dato);
if (!this.raiz) {
this.raiz = nuevoNodo;
} else {
this.#insertarNodo(this.raiz, nuevoNodo);
}
}
#insertarNodo(nodo, nuevoNodo) {
if (nuevoNodo.dato < nodo.dato) {
if (!nodo.izquierda) {
nodo.izquierda = nuevoNodo;
} else {
this.#insertarNodo(nodo.izquierda, nuevoNodo);
}
} else {
if (!nodo.derecha) {
nodo.derecha = nuevoNodo;
} else {
this.#insertarNodo(nodo.derecha, nuevoNodo);
}
}
}
}
const arbol = new ArbolBinario();
arbol.insertar(10);
arbol.insertar(5);
arbol.insertar(15);
console.log(arbol);
PHP
Un árbol binrio puede implementarse usando clases.
class Nodo {
public $dato;
public $izquierda = null;
public $derecha = null;
public function __construct($dato) {
$this->dato = $dato;
}
}
class ArbolBinario {
public $raiz = null;
public function insertar($dato) {
$nuevoNodo = new Nodo($dato);
if ($this->raiz === null) {
$this->raiz = $nuevoNodo;
} else {
$this->insertarNodo($this->raiz, $nuevoNodo);
}
}
private function insertarNodo($nodo, $nuevoNodo) {
if ($nuevoNodo->dato < $nodo->dato) {
if ($nodo->izquierda === null) {
$nodo->izquierda = $nuevoNodo;
} else {
$this->insertarNodo($nodo->izquierda, $nuevoNodo);
}
} else {
if ($nodo->derecha === null) {
$nodo->derecha = $nuevoNodo;
} else {
$this->insertarNodo($nodo->derecha, $nuevoNodo);
}
}
}
}
$arbol = new ArbolBinario();
$arbol->insertar(10);
$arbol->insertar(5);
$arbol->insertar(15);
print_r($arbol);
C#
Podemos implementar un árbol binario de búsqueda con clases.
using System;
class Nodo {
public int Dato;
public Nodo Izquierda, Derecha;
public Nodo(int dato) {
Dato = dato;
Izquierda = Derecha = null;
}
}
class ArbolBinario {
public Nodo Raiz;
public void Insertar(int dato) {
Raiz = InsertarNodo(Raiz, dato);
}
private Nodo InsertarNodo(Nodo nodo, int dato) {
if (nodo == null) return new Nodo(dato);
if (dato < nodo.Dato) nodo.Izquierda = InsertarNodo(nodo.Izquierda, dato);
else nodo.Derecha = InsertarNodo(nodo.Derecha, dato);
return nodo;
}
}
class Program {
static void Main() {
ArbolBinario arbol = new ArbolBinario();
arbol.Insertar(10);
arbol.Insertar(5);
arbol.Insertar(15);
Console.WriteLine("Árbol creado.");
}
}
Java
Un árbol binario de búsqueda se implementa fácilmente con clases.
class Nodo {
int dato;
Nodo izquierda, derecha;
public Nodo(int dato) {
this.dato = dato;
izquierda = derecha = null;
}
}
class ArbolBinario {
Nodo raiz;
void insertar(int dato) {
raiz = insertarNodo(raiz, dato);
}
Nodo insertarNodo(Nodo nodo, int dato) {
if (nodo == null) {
return new Nodo(dato);
}
if (dato < nodo.dato) {
nodo.izquierda = insertarNodo(nodo.izquierda, dato);
} else {
nodo.derecha = insertarNodo(nodo.derecha, dato);
}
return nodo;
}
}
public class Main {
public static void main(String[] args) {
ArbolBinario arbol = new ArbolBinario();
arbol.insertar(10);
arbol.insertar(5);
arbol.insertar(15);
System.out.println("Árbol creado.");
}
}
C
Un árbol binario requiere estructuras y punteros.
#include <stdio.h>
#include <stdlib.h>
typedef struct Nodo {
int dato;
struct Nodo* izquierda;
struct Nodo* derecha;
} Nodo;
Nodo* crearNodo(int dato) {
Nodo* nuevo = (Nodo*)malloc(sizeof(Nodo));
nuevo->dato = dato;
nuevo->izquierda = nuevo->derecha = NULL;
return nuevo;
}
Nodo* insertar(Nodo* raiz, int dato) {
if (raiz == NULL) return crearNodo(dato);
if (dato < raiz->dato)
raiz->izquierda = insertar(raiz->izquierda, dato);
else
raiz->derecha = insertar(raiz->derecha, dato);
return raiz;
}
int main() {
Nodo* raiz = NULL;
raiz = insertar(raiz, 10);
insertar(raiz, 5);
insertar(raiz, 15);
printf("Árbol creado.\n");
return 0;
}
C++
Un árbol binario de búsqueda se implementa fácilmente con clases.
#include <iostream>
using namespace std;
struct Nodo {
int dato;
Nodo* izquierda;
Nodo* derecha;
Nodo(int d) : dato(d), izquierda(nullptr), derecha(nullptr) {}
};
class ArbolBinario {
public:
Nodo* raiz;
ArbolBinario() : raiz(nullptr) {}
void insertar(int dato) {
raiz = insertarNodo(raiz, dato);
}
private:
Nodo* insertarNodo(Nodo* nodo, int dato) {
if (!nodo) return new Nodo(dato);
if (dato < nodo->dato)
nodo->izquierda = insertarNodo(nodo->izquierda, dato);
else
nodo->derecha = insertarNodo(nodo->derecha, dato);
return nodo;
}
};
int main() {
ArbolBinario arbol;
arbol.insertar(10);
arbol.insertar(5);
arbol.insertar(15);
cout << "Árbol creado." << endl;
return 0;
}