Fundamentos de Algoritmos en JavaScript: Esenciales y Aplicaciones Prácticas

En el desarrollo de software, los algoritmos son el conjunto de instrucciones definidas que transforman una estructura de datos de entrada en una de salida. A continuación, se exploran algoritmos fundamentales y comunes en JavaScript.

Algoritmos de Ordenamiento

Bubble Sort

Este método compara repetidamente elementos adyacentes y los intercambia si están en el orden incorrecto.

function bubbleSort(array) {
    let len = array.length;
    for (let i = 0; i < len; i++) {
        for (let j = 0; j < len - 1 - i; j++) {
            if (array[j] > array[j+1]) {
                [array[j], array[j+1]] = [array[j+1], array[j]];
            }
        }
    }
    return array;
}

Isnertion Sort

Construye el array ordenado final un elemento a la vez, insertando cada nuevo elemento en su posición correcta dentro de la porción ya ordenaad. Su complejidad temporal promedio es O(n²), lo que lo hace adecuado para conjuntos de datos pequeños.

function insertionSort(arr) {
    let n = arr.length;
    for (let i = 1; i < n; i++) {
        let current = arr[i];
        let j = i - 1;
        while (j >= 0 && arr[j] > current) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = current;
    }
    return arr;
}

Quick Sort

Es un algoritmo eficiente que utiliza la estrategia de "divide y vencerás". Una implementación simple elige un pivote, particiona el array en elementos menores y mayores que el pivote, y luego ordena recursivamente las particiones.

function quickSort(arr) {
    if (arr.length <= 1) return arr;
    const pivot = arr[0];
    const left = [];
    const right = [];
    for (let i = 1; i < arr.length; i++) {
        arr[i] < pivot ? left.push(arr[i]) : right.push(arr[i]);
    }
    return [...quickSort(left), pivot, ...quickSort(right)];
}

Para optimizar el uso de memoria, se puede implementar una partición en el lugar (in-place), que modifica el array original sin crear nuevos arrays en cada recursión.

function quickSortInPlace(arr, left = 0, right = arr.length - 1) {
    if (left < right) {
        const pivotIndex = partition(arr, left, right);
        quickSortInPlace(arr, left, pivotIndex - 1);
        quickSortInPlace(arr, pivotIndex + 1, right);
    }
    return arr;
}

function partition(arr, left, right) {
    const pivot = arr[right];
    let i = left;
    for (let j = left; j < right; j++) {
        if (arr[j] < pivot) {
            [arr[i], arr[j]] = [arr[j], arr[i]];
            i++;
        }
    }
    [arr[i], arr[right]] = [arr[right], arr[i]];
    return i;
}

Operaciones con Cadenas (Strings)

Palíndromo

Verifica si una cadena se lee igual hacia adelante y hacia atrás, ignorando mayúsculas y caracteres no alfanuméricos.

function esPalindromo(str) {
    const limpio = str.toLowerCase().replace(/[\W_]/g, '');
    return limpio === limpio.split('').reverse().join('');
}

Invertir una Cadena

function invertirCadena(str) {
    return str.split('').reverse().join('');
}

Carácter con Mayor Frecuencia

function maxFrecuencia(str) {
    const contador = {};
    let maxChar = '';
    let maxCont = 0;
    for (const char of str) {
        contador[char] = (contador[char] || 0) + 1;
        if (contador[char] > maxCont) {
            maxCont = contador[char];
            maxChar = char;
        }
    }
    return maxChar;
}

Operaciones con Arrays

Eliminar Duplicados

function uniqArray(arr) {
    return [...new Set(arr)];
}
// Alternativa sin Set
function uniqArrayManual(arr) {
    const sinDuplicados = [];
    for (const item of arr) {
        if (!sinDuplicados.includes(item)) {
            sinDuplicados.push(item);
        }
    }
    return sinDuplicados;
}

Algoritmos de Búsqueda

Búsqueda Binaria

Requiere un array ordenado. Reduce a la mitad el espacio de búsqueda en cada paso, alcanzando una complejidad temporal de O(log n).

function busquedaBinaria(arr, valor) {
    let inicio = 0;
    let fin = arr.length - 1;
    while (inicio <= fin) {
        const medio = Math.floor((inicio + fin) / 2);
        if (arr[medio] === valor) return medio;
        else if (arr[medio] < valor) inicio = medio + 1;
        else fin = medio - 1;
    }
    return -1;
}

Recorrido de Árboles

Búsqueda en Profundidad (DFS)

function dfsIterativo(raiz) {
    const resultado = [];
    const pila = [raiz];
    while (pila.length > 0) {
        const nodo = pila.pop();
        resultado.push(nodo);
        if (nodo.children) {
            for (let i = nodo.children.length - 1; i >= 0; i--) {
                pila.push(nodo.children[i]);
            }
        }
    }
    return resultado;
}

Búsqueda en Amplitud (BFS)

function bfsIterativo(raiz) {
    const resultado = [];
    const cola = [raiz];
    while (cola.length > 0) {
        const nodo = cola.shift();
        resultado.push(nodo);
        if (nodo.children) {
            for (const hijo of nodo.children) {
                cola.push(hijo);
            }
        }
    }
    return resultado;
}

Algoritmos con Funciones de Orden Superior

Deduplicación con Filter

const arrOriginal = ['a', 'b', 'c', 'a', 'b'];
const arrUnico = arrOriginal.filter((elemento, indice, self) => {
    return self.indexOf(elemento) === indice;
});

Ordenamiento Personalizado con Sort

El método sort() por defecto convierte elementos a cadenas y ordena según el código Unicode. Para un ordenamiento numérico correcto, se debe proporcionar una función de comparación.

const numeros = [10, 20, 1, 2];
numeros.sort((a, b) => a - b); // Orden ascendente: [1, 2, 10, 20]

Es importante notar que sort() modifica el array original y retorna una referencia al mismo.

Etiquetas: JavaScript algoritmos ordenamiento búsqueda estructuras de datos

Publicado el 7-7 23:19