Tabla de contenido
- ¿Por qué aprender estructuras de datos?
- Array (Arreglo)
- Lista Enlazada
- Pila (Stack)
- Cola (Queue)
- ¿Cuándo usar cada estructura?
Las estructuras de datos son una de esas materias que muchos desarrolladores evitan porque suena complicado, pero son fundamentales para escribir código eficiente. No necesitas ser un científico computacional para entenderlas: son formas de organizar datos según el problema que quieres resolver.
¿Por qué aprender estructuras de datos?
Imagina que tienes que gestionar 1 millón de registros. Dependiendo de qué estructura uses, una operación puede tardar microsegundos o varios minutos. La diferencia está en elegir la herramienta correcta.
Además, son preguntas frecuentes en entrevistas técnicas de trabajo. Pero más importante que eso: entenderlas te hace mejor programador porque te obliga a pensar en la eficiencia de tu código.
Array (Arreglo)
El array es la estructura más básica. Es una colección de elementos almacenados en posiciones contiguas de memoria, accesibles por su índice numérico.
const frutas = ["manzana", "pera", "naranja", "uva"];
// Acceso por índice (O(1) - instantáneo)
console.log(frutas[0]); // "manzana"
console.log(frutas[2]); // "naranja"
// Modificar
frutas[1] = "mango";
// Agregar al final (O(1) amortizado)
frutas.push("sandía");
// Eliminar del final (O(1))
frutas.pop();
// Agregar al inicio (O(n) - costoso, mueve todos los elementos)
frutas.unshift("fresa");
// Eliminar del inicio (O(n) - costoso)
frutas.shift();
// Buscar (O(n) - hay que revisar uno por uno)
const idx = frutas.indexOf("pera");
Fortalezas del array:
- Acceso instantáneo por índice
- Iteración eficiente
- Poco overhead de memoria
Debilidades:
- Insertar/eliminar en el medio o inicio es costoso (hay que mover elementos)
- En algunos lenguajes tiene tamaño fijo
Lista Enlazada
Una lista enlazada es una serie de nodos donde cada nodo contiene un valor y una referencia (puntero) al siguiente nodo. A diferencia del array, los nodos no necesitan estar en posiciones contiguas de memoria.
// Nodo individual
class Nodo {
constructor(valor) {
this.valor = valor;
this.siguiente = null;
}
}
// Lista enlazada simple
class ListaEnlazada {
constructor() {
this.cabeza = null;
this.tamano = 0;
}
// Agregar al inicio (O(1))
prepend(valor) {
const nuevo = new Nodo(valor);
nuevo.siguiente = this.cabeza;
this.cabeza = nuevo;
this.tamano++;
}
// Agregar al final (O(n))
append(valor) {
const nuevo = new Nodo(valor);
if (!this.cabeza) {
this.cabeza = nuevo;
} else {
let actual = this.cabeza;
while (actual.siguiente) {
actual = actual.siguiente;
}
actual.siguiente = nuevo;
}
this.tamano++;
}
// Imprimir todos los valores
imprimir() {
let actual = this.cabeza;
const valores = [];
while (actual) {
valores.push(actual.valor);
actual = actual.siguiente;
}
console.log(valores.join(" → "));
}
}
const lista = new ListaEnlazada();
lista.append("A");
lista.append("B");
lista.append("C");
lista.prepend("inicio");
lista.imprimir(); // "inicio → A → B → C"
Fortalezas:
- Insertar/eliminar al inicio es O(1)
- Tamaño dinámico (no hay que declarar el tamaño)
Debilidades:
- Acceder a un elemento requiere recorrer la lista desde el inicio (O(n))
- Más memoria por los punteros
Pila (Stack)
Una pila (stack) es una estructura LIFO: Last In, First Out. El último elemento en entrar es el primero en salir. Piensa en una pila de platos: solo puedes poner o quitar desde arriba.
class Pila {
constructor() {
this.items = [];
}
// Agregar al tope (O(1))
push(elemento) {
this.items.push(elemento);
}
// Sacar del tope (O(1))
pop() {
if (this.estaVacia()) return null;
return this.items.pop();
}
// Ver el tope sin quitar (O(1))
peek() {
return this.items[this.items.length - 1];
}
estaVacia() {
return this.items.length === 0;
}
tamano() {
return this.items.length;
}
}
const pila = new Pila();
pila.push("A");
pila.push("B");
pila.push("C");
console.log(pila.peek()); // "C" (tope)
console.log(pila.pop()); // "C" (sale primero el último en entrar)
console.log(pila.pop()); // "B"
console.log(pila.peek()); // "A"
Casos de uso reales:
- El historial de Ctrl+Z en editores
- La pila de llamadas (call stack) de JavaScript
- Validación de paréntesis equilibrados (
()[]{}) - Navegación hacia atrás en un navegador
Cola (Queue)
Una cola (queue) es una estructura FIFO: First In, First Out. El primero en entrar es el primero en salir. Como una fila del banco: el primero que llegó es el primero que se atiende.
class Cola {
constructor() {
this.items = [];
}
// Agregar al final (enqueue)
enqueue(elemento) {
this.items.push(elemento);
}
// Sacar del inicio (dequeue)
dequeue() {
if (this.estaVacia()) return null;
return this.items.shift();
}
// Ver el frente sin quitar
frente() {
return this.items[0];
}
estaVacia() {
return this.items.length === 0;
}
}
const cola = new Cola();
cola.enqueue("Usuario 1");
cola.enqueue("Usuario 2");
cola.enqueue("Usuario 3");
console.log(cola.dequeue()); // "Usuario 1" (primero en entrar)
console.log(cola.dequeue()); // "Usuario 2"
console.log(cola.frente()); // "Usuario 3"
Casos de uso reales:
- Cola de impresión
- Sistema de mensajes/notificaciones
- Procesamiento de tareas en orden (job queues)
- BFS (Breadth-First Search) en grafos
¿Cuándo usar cada estructura?
| Estructura | Usar cuando… | Ejemplo |
|---|---|---|
| Array | Necesitas acceso rápido por índice o iterar en orden | Lista de productos, datos de tabla |
| Lista enlazada | Insertas/eliminas frecuentemente al inicio | Historial de acciones |
| Pila (Stack) | Necesitas LIFO: el último en entrar sale primero | Deshacer acciones, call stack |
| Cola (Queue) | Necesitas FIFO: el primero en entrar sale primero | Cola de espera, mensajes |
Dominar estas cuatro estructuras básicas te dará las bases para entender estructuras más avanzadas como árboles, grafos y tablas hash. Todo se construye sobre estos fundamentos.