Algoritmos y estructuras de datos en TypeScript: de principiante a profesional
Los algoritmos y las estructuras de datos son la base sobre la que se construye todo el desarrollo de software moderno. Independientemente de si escribes frontend en React, backend en Node.js o una aplicación móvil, una comprensión profunda de estos conceptos te permite crear aplicaciones eficientes, escalables y rápidas. En este artículo, analizaremos en detalle los algoritmos y estructuras de datos clave en TypeScript, un lenguaje que combina la flexibilidad de JavaScript con el rigor del tipado estático.
TypeScript es ideal para aprender algoritmos: el tipado estricto ayuda a evitar errores en la etapa de compilación, y la compatibilidad con genéricos (generics) permite crear estructuras de datos universales y reutilizables. Comenzaremos con conceptos simples y pasaremos gradualmente a temas más complejos, acompañando cada paso con ejemplos de código claros.
1. Estructuras de datos básicas: Pila y Cola
La Pila (Stack) y la Cola (Queue) son estructuras de datos lineales básicas que se utilizan en todas partes: desde la gestión del historial del navegador hasta la planificación de tareas en sistemas operativos. Veamos su implementación en TypeScript.
Pila (LIFO — Last In, First Out)
La pila funciona bajo el principio "último en entrar, primero en salir". Las operaciones principales son: push (agregar elemento) y pop (extraer el último elemento).
class Stack<T> { private items: T[] = [];
push(element: T): void { this.items.push(element); }
pop(): T | undefined { return this.items.pop(); }
peek(): T | undefined { return this.items[this.items.length - 1]; }
isEmpty(): boolean { return this.items.length === 0; }
size(): number { return this.items.length; }}
// Ejemplo de usoconst stack = new Stack<number>();stack.push(1);stack.push(2);stack.push(3);console.log(stack.pop()); // 3console.log(stack.peek()); // 2Cola (FIFO — First In, First Out)
La cola funciona bajo el principio "primero en entrar, primero en salir". Las operaciones principales son: enqueue (agregar al final) y dequeue (extraer del principio).
class Queue<T> { private items: T[] = [];
enqueue(element: T): void { this.items.push(element); }
dequeue(): T | undefined { return this.items.shift(); }
front(): T | undefined { return this.items[0]; }
isEmpty(): boolean { return this.items.length === 0; }
size(): number { return this.items.length; }}
// Ejemplo de usoconst queue = new Queue<string>();queue.enqueue("Primero");queue.enqueue("Segundo");queue.enqueue("Tercero");console.log(queue.dequeue()); // "Primero"console.log(queue.front()); // "Segundo"2. Algoritmos de búsqueda: Búsqueda Lineal y Binaria
La búsqueda de datos es una de las operaciones más comunes en programación. Veremos dos enfoques principales: la búsqueda lineal (simple pero lenta) y la búsqueda binaria (rápida pero que requiere datos ordenados).
Búsqueda Lineal
El algoritmo verifica secuencialmente cada elemento del array hasta encontrar el objetivo. Complejidad temporal: O(n).
function linearSearch<T>(arr: T[], target: T): number { for (let i = 0; i < arr.length; i++) { if (arr[i] === target) { return i; // Devuelve el índice del elemento encontrado } } return -1; // Elemento no encontrado}
// Ejemploconst numbers = [10, 20, 30, 40, 50];console.log(linearSearch(numbers, 30)); // 2console.log(linearSearch(numbers, 60)); // -1Búsqueda Binaria
La búsqueda binaria solo funciona en arrays ordenados. Divide el array por la mitad en cada paso, descartando la mitad