Cómo implementar una lista enlazada en JavaScript: paso a paso

Go to Homepage

Aprende cómo implementar una lista enlazada en JavaScript de manera sencilla y eficiente

Si eres un desarrollador de JavaScript, es probable que hayas oído hablar de las listas enlazadas pero no sabes exactamente lo que son o cómo implementarlas en tu código. ¡No te preocupes, estás en el lugar correcto! En esta guía, te mostraremos cómo implementar una lista enlazada en JavaScript paso a paso.

¿Qué es una lista enlazada?

En términos simples, una lista enlazada es una colección de elementos donde cada elemento, conocido como nodo, tiene un enlace al siguiente nodo. Esto significa que los nodos están conectados entre sí de forma secuencial y forman una cadena.

Una lista enlazada se puede utilizar en muchas aplicaciones diferentes, como aplicaciones de comercio electrónico para manejar pedidos y de ventas o en la construcción de estructuras más complejas, como redes sociales.

Implementación de lista enlazada en JavaScript La implementación de la lista enlazada en JavaScript se puede dividir en tres partes: estructura de datos de la lista, el nodo y el método de inserción.

1. Estructura de datos de la lista

Para comenzar, necesitamos definir la estructura de nuestra lista enlazada. Crearemos una clase LL que tendrá dos propiedades: la cabeza y la longitud.

class LL {
    constructor() {
        this.head = null;
        this.length = 0;
    }
}

2. Nodo

Ahora, debemos definir el nodo de nuestra lista enlazada. Cada nodo tendrá dos propiedades: valor y siguiente.

class Node {
    constructor(value) {
        this.value = value;
        this.next = null;
    }
}

3. Método de inserción

Finalmente, necesitamos definir un método para agregar elementos a nuestra lista enlazada. Este método añadirá un nuevo nodo al final de la lista.

class LL {
    constructor() {
        this.head = null;
        this.length = 0;
    }

    add(value) {
        const newNode = new Node(value);

        if (!this.head) {
            this.head = newNode;
        } else {
            let current = this.head;

            while (current.next) {
                current = current.next;
            }

            current.next = newNode;
        }

        this.length++;
    }
}

¡Y eso es todo! Con estas tres partes, hemos construido una lista enlazada completa.

Las listas enlazadas son muy útiles para almacenar datos y estructuras. La implementación de una lista enlazada puede parecer intimidante, pero siguiendo estos pasos básicos podrás crear una lista enlazada completamente funcional.

Definición y funcionamiento de la estructura de una lista enlazada

Antes de comenzar a implementar una lista enlazada en JavaScript, es importante entender su estructura y cómo funciona. En esencia, una lista enlazada es una estructura de datos que consiste en nodos conectados entre sí a través de punteros.

Cada nodo contiene dos elementos: una referencia al siguiente nodo en la lista y un valor. La referencia al siguiente nodo es conocida como puntero o enlace, y es lo que da a la lista enlazada su nombre.

La lista enlazada se empieza con un nodo llamado cabeza o raíz, que es el primer elemento de la lista. A medida que se agregan nuevos elementos a la lista, se crea un nuevo nodo y se inserta después del último nodo existente en la lista.

Cuando se busca un valor en una lista enlazada, el proceso es diferente al hacerlo en un arreglo. En lugar de buscar en todos los elementos uno por uno, la búsqueda comienza en el nodo de la cabeza y se sigue avanzando en la lista a través de los punteros hasta encontrar el valor buscado o llegar al final de la lista.

Una de las mayores ventajas de las listas enlazadas es que permiten la inserción y eliminación de elementos en cualquier posición de manera eficiente. Esto se debe a que no es necesario mover todos los elementos de la lista como en un arreglo, sino simplemente actualizar los punteros de los nodos a su alrededor.

Sin embargo, una desventaja de las listas enlazadas es que no permiten el acceso directo a elementos aleatorios como en un arreglo, ya que para acceder a un elemento en particular es necesario recorrer la lista desde el nodo de la cabeza hasta el elemento deseado.

Una lista enlazada es una estructura de datos que consiste en nodos conectados a través de punteros. Cada nodo contiene una referencia al siguiente nodo y un valor. La búsqueda en una lista enlazada se realiza siguiendo los punteros desde el nodo de la cabeza hasta encontrar el valor deseado. La inserción y eliminación de nodos es más eficiente que en un arreglo, pero no permite el acceso aleatorio a elementos. En la sección siguiente, echaremos un vistazo a cómo implementar una lista enlazada en JavaScript, utilizando todo lo que hemos aprendido aquí.

Las ventajas y desventajas de usar una lista enlazada en tus proyectos

Si estás familiarizado con la programación, seguramente habrás escuchado hablar de las listas enlazadas en alguna ocasión. Las listas enlazadas son una estructura de datos que permite almacenar elementos de manera consecutiva en memoria, pero que a diferencia de los arreglos, no necesitan ser contiguos.

Las listas enlazadas son utilizadas en muchos proyectos y hay varias razones para ello. A continuación, te vamos a contar las ventajas y desventajas de utilizar listas enlazadas en tus proyectos:

Ventajas

Flexibilidad en la inserción y eliminación de elementos

Una de las principales ventajas de las listas enlazadas es que proporcionan una gran flexibilidad a la hora de insertar y eliminar elementos. Por ejemplo, si quieres agregar un nuevo elemento al principio de una lista enlazada, simplemente necesitas crear un nuevo nodo, enlazarlo al primer nodo de la lista y establecer este nuevo nodo como el primero de la lista. Del mismo modo, si quieres eliminar un nodo, solo necesitas cambiar los punteros que enlazan los nodos.

// Implementación de una nueva lista enlazada
class Nodo {
    constructor(valor, siguiente = null) {
        this.valor = valor;
        this.siguiente = siguiente;
    }
}

class ListaEnlazada {
    constructor() {
        this.primero = null;
    }

    agregarAlInicio(valor) {
        this.primero = new Nodo(valor, this.primero); // Creando un nuevo nodo y enlazándolo al primer nodo
    }

    eliminarInicio() {
        if (this.primero !== null) {
            this.primero = this.primero.siguiente; // Apuntando el primer nodo al segundo nodo
        }
    }
}

Optimización del uso de la memoria

Otra ventaja de las listas enlazadas es que optimizan el uso de la memoria. Esto se debe a que no necesitan reservar un bloque de memoria contiguo para almacenar su contenido.

Por ejemplo, si creamos un arreglo para almacenar 1 millón de elementos, ese arreglo ocupará un espacio de memoria fijo en el orden de los megabytes, incluso si solo hemos utilizado una pequeña porción del arreglo. En contraste, una lista enlazada solo utilizará la cantidad de memoria necesaria para almacenar los elementos que contiene y, por tanto, será mucho más eficiente en términos de memoria en proyectos con datos de gran tamaño.

// Creando una lista enlazada
const lista = new ListaEnlazada();

for (let i = 0; i < 1000000; i++) {
    lista.agregarAlInicio(i);
}

// A diferencia de un arreglo, la lista enlazada solo ocupa la memoria necesaria para almacenar los elementos

Desventajas

Pérdida de rendimiento en el acceso aleatorio

Aunque las listas enlazadas permiten un fácil acceso a los elementos en el sentido de izquierda a derecha, su desempeño se ve afectado en el acceso aleatorio.

A diferencia de un arreglo, que almacena sus elementos en un bloque de memoria contiguo, las listas enlazadas almacenan los diferentes nodos en diferentes ubicaciones en memoria. Por eso, si intentamos acceder a elementos aleatorios en una lista enlazada, el rendimiento se verá afectado debido a que el programa tendrá que pasar por cada nodo de la lista para llegar al elemento deseado.

// Agregar elementos a una lista enlazada
const lista = new ListaEnlazada();

for (let i = 0; i < 1000000; i++) {
    lista.agregarAlInicio(i);
}

// Buscar un elemento aleatorio en una lista enlazada
let buscar = 1000;
let nodoActual = lista.primero;

while (nodoActual.valor !== buscar) {
    // Se atraviesa toda la lista para encontrar el elemento deseado
    nodoActual = nodoActual.siguiente;
}

Es importante tener en cuenta que cada proyecto tiene requerimientos y objetivos específicos, por lo que la elección de estructuras de datos dependerá profundamente del contexto de trabajo. En estos casos te sugerimos evaluar tus propias necesidades y verificar si las características de las listas enlazadas se adaptan a tus neces

Paso a paso: creando un nodo para la lista enlazada

Una lista enlazada es una estructura de datos que permite almacenar y manipular un conjunto de elementos. En JavaScript, podemos implementar una lista enlazada utilizando objetos y referencias.

Antes de empezar a construir la lista enlazada, es importante definir el concepto de nodo. Un nodo es un objeto que contiene un elemento y una referencia al siguiente nodo de la lista. Cada nodo se conecta con el siguiente mediante la referencia que contiene.

Para crear un nodo en JavaScript, podemos utilizar una función constructora que nos permita crear instancias con las propiedades que necesitamos. En este caso, necesitamos una propiedad para almacenar el elemento que queremos agregar a la lista y otra propiedad para guardar la referencia al siguiente nodo.

El código para crear una función constructora de nodos sería el siguiente:

function Node(element) {
    this.element = element;
    this.next = null;
}

En esta función constructora, element es el valor que queremos almacenar en el nodo y next es la referencia al siguiente nodo de la lista. Inicialmente, el valor de next es null, ya que el nodo que estamos creando todavía no está conectado a ningún otro nodo.

Para crear un nodo, podemos instanciar la función constructora y pasarle el valor que deseamos almacenar. Por ejemplo, si queremos crear un nodo con el valor "apple", podemos hacer lo siguiente:

var appleNode = new Node("apple");

Este código crea una nueva instancia de la función constructora Node y asigna la cadena "apple" al valor de la propiedad element.

Ahora bien, para crear una lista enlazada, tendremos que crear varios nodos y conectarlos entre sí mediante la propiedad next. En el próximo paso, explicaremos cómo hacer esto creando una función de enlace que creará la conexión entre los nodos.

Para crear un nodo en una lista enlazada en JavaScript necesitamos:

  1. Definir una función constructora que tenga como propiedades el elemento a almacenar y la referencia al siguiente nodo.
  2. Instanciar la función constructora y pasarle el elemento a almacenar como parámetro.
  3. Utilizar la referencia del nodo para conectarlo con el siguiente nodo de la lista.

Cómo agregar y eliminar elementos en una lista enlazada

Si deseas trabajar con estructuras de datos en tu proyecto de JavaScript, las listas enlazadas pueden ser una buena opción. En este artículo ya hemos aprendido cómo implementar una lista enlazada en JavaScript, pero en este apartado te enseñaré cómo agregar y eliminar elementos.

Para agregar un elemento al final de la lista enlazada, primero necesitamos saber si la lista está vacía o no. Si está vacía, simplemente asignamos el nuevo nodo a la cabeza de la lista. Si no lo está, recorremos la lista hasta que encontremos el último nodo y luego lo enlazamos con el nuevo nodo.

// Agrega un elemento al final de la lista
function agregarAlFinal(dato) {
    const nodoNuevo = new Nodo(dato);
    if (!this.cabeza) {
        this.cabeza = nodoNuevo;
        return;
    }
    let nodoActual = this.cabeza;
    while (nodoActual.siguiente) {
        nodoActual = nodoActual.siguiente;
    }
    nodoActual.siguiente = nodoNuevo;
}

También es posible agregar un elemento al principio de la lista. Para hacerlo, simplemente asignamos el nuevo nodo a la cabeza de la lista y hacemos que el próximo nodo sea el que antes era la cabeza.

// Agrega un elemento al principio de la lista
function agregarAlInicio(dato) {
    const nodoNuevo = new Nodo(dato);
    nodoNuevo.siguiente = this.cabeza;
    this.cabeza = nodoNuevo;
}

Ahora, para eliminar un elemento, primero debemos encontrar su nodo anterior. Una vez que lo encontramos, podemos simplemente hacer que su nodo siguiente sea el siguiente del nodo que queremos eliminar.

// Elimina el primer elemento de la lista
function eliminarPrimero() {
    if (!this.cabeza) {
        console.log("La lista está vacía");
        return;
    }
    this.cabeza = this.cabeza.siguiente;
}

// Elimina el último elemento de la lista
function eliminarUltimo() {
    if (!this.cabeza) {
        console.log("La lista está vacía");
        return;
    }
    if (!this.cabeza.siguiente) {
        this.cabeza = null;
        return;
    }
    let nodoActual = this.cabeza;
    while (nodoActual.siguiente.siguiente) {
        nodoActual = nodoActual.siguiente;
    }
    nodoActual.siguiente = null;
}

Por último, también podemos eliminar un elemento en cualquier posición de la lista. Para hacerlo, primero debemos encontrar el nodo anterior y luego hacer que su nodo siguiente sea el siguiente del nodo que queremos eliminar.

// Elimina un elemento en una posición específica de la lista
function eliminarEnPosicion(posicion) {
    if (!this.cabeza) {
        console.log("La lista está vacía");
        return;
    }
    if (posicion === 0) {
        this.cabeza = this.cabeza.siguiente;
        return;
    }
    let nodoActual = this.cabeza;
    let contador = 0;
    while (nodoActual) {
        if (contador === posicion - 1) {
            nodoActual.siguiente = nodoActual.siguiente.siguiente;
            return;
        }
        contador++;
        nodoActual = nodoActual.siguiente;
    }
    console.log(`La lista no tiene ${posicion} elementos`);
}

Agregar y eliminar elementos en una lista enlazada es bastante sencillo. Con estas funciones tendrás la capacidad de manipular los datos de la lista de manera adecuada y obtener el rendimiento que esperas de esta estructura de datos.

La importancia de la recursividad en la implementación de una lista enlazada

La recursividad es una técnica de programación que se basa en la idea de que una función puede invocarse a sí misma para solucionar un problema. En la implementación de una lista enlazada en JavaScript, la recursividad es una herramienta que nos permite recorrer y manipular los nodos de la lista de forma eficiente.

En una lista enlazada, cada nodo tiene un puntero que apunta al siguiente nodo de la lista. Para recorrer la lista, es necesario que una función vaya siguiendo estos punteros para acceder a cada uno de los nodos. La recursividad es muy útil en este caso, ya que nos permite definir una función que se encargue de recorrer la lista y que, a su vez, se invoque a sí misma para recorrer los nodos siguientes.

Veamos un ejemplo:

function imprimirLista(nodo) {
    console.log(nodo.valor);
    if (nodo.siguiente !== null) {
        imprimirLista(nodo.siguiente);
    }
}

En este ejemplo, la función imprimirLista recibe un nodo como parámetro y lo imprime por consola. Después, comprueba si el nodo tiene un siguiente nodo (es decir, si no es el último nodo de la lista) y, en caso afirmativo, se invoca a sí misma pasándole como parámetro el siguiente nodo. De esta forma, la función va recorriendo la lista y se detiene cuando llega al último nodo.

Otro ejemplo de la importancia de la recursividad en la implementación de una lista enlazada es la función que se encarga de eliminar un nodo de la lista. Para ello, es necesario ajustar los punteros de los nodos previo y siguiente al nodo que se va a eliminar. La recursividad nos ayuda a recorrer la lista y encontrar el nodo que queremos eliminar, y a la vez nos permite modificar los punteros de forma eficiente.

Veamos un ejemplo de cómo eliminar un nodo de la lista:

function eliminarNodo(nodo, valor) {
    if (nodo === null) {
        return null;
    }
    if (nodo.valor === valor) {
        return nodo.siguiente;
    }
    nodo.siguiente = eliminarNodo(nodo.siguiente, valor);
    return nodo;
}

En esta función, se recibe como parámetros el nodo actual y el valor del nodo que se va a eliminar. Primero se comprueba si el nodo actual es nulo, en cuyo caso se devuelve nulo. Después, se comprueba si el valor del nodo actual es igual al valor que se quiere eliminar. Si es así, se devuelve el siguiente nodo de la lista, eliminando así el nodo actual. Si el valor del nodo actual no es igual al valor que se quiere eliminar, se invoca a la función pasándole como parámetro el siguiente nodo de la lista, y se ajusta el puntero siguiente del nodo actual para que apunte al siguiente nodo de la lista que se ha retornado. De esta forma, se va recorriendo la lista hasta encontrar el nodo que se quiere eliminar.

La recursividad es una técnica poderosa que nos permite recorrer y manipular los nodos de una lista enlazada de forma eficiente. Su uso es fundamental en la implementación de operaciones como la inserción, eliminación y búsqueda de elementos en la lista. La aplicación correcta de la recursividad en la implementación de una lista enlazada puede hacer una gran diferencia en la eficiencia de nuestro código.

Casos de uso comunes para una lista enlazada en proyectos de JavaScript

En proyectos de JavaScript, una lista enlazada es una estructura de datos muy útil que puede ayudar a resolver muchos problemas. A continuación, vamos a explorar algunos casos de uso comunes para una lista enlazada en proyectos de JavaScript.

Una lista enlazada es especialmente efectiva cuando se necesita insertar o eliminar elementos en una estructura de datos de manera constante. Esto se debe a que, en una lista enlazada, cada elemento en la estructura tiene una referencia al siguiente elemento en la lista. Como resultado, agregar o eliminar elementos en una lista enlazada es mucho más eficiente que hacerlo en un array tradicional.

Una manera común en la que se usa una lista enlazada en proyectos de JavaScript es para implementar una pila. Una pila es una estructura de datos que permite agregar y eliminar elementos en el “último en entrar, primero en salir” (LIFO por sus siglas en inglés). Una forma de implementar una pila en JavaScript con una lista enlazada sería:

class Pila {
    constructor() {
        this.head = null;
        this.size = 0;
    }

    push(value) {
        const node = { value, next: null };
        node.next = this.head;
        this.head = node;
        this.size++;
    }

    pop() {
        if (!this.head) return null;

        const value = this.head.value;
        this.head = this.head.next;
        this.size--;

        return value;
    }
}

Otra forma en que se utiliza una lista enlazada es para implementar una cola. Una cola es una estructura de datos que permite agregar elementos al final y eliminar elementos del principio en el “primero en entrar, primero en salir” (FIFO por sus siglas en inglés). Una forma de implementar una cola en JavaScript con una lista enlazada sería:

class Cola {
    constructor() {
        this.head = null;
        this.tail = null;
        this.size = 0;
    }

    enqueue(value) {
        const node = { value, next: null };
        if (!this.head) {
            this.head = node;
        } else {
            this.tail.next = node;
        }
        this.tail = node;
        this.size++;
    }

    dequeue() {
        if (!this.head) return null;

        const value = this.head.value;
        this.head = this.head.next;
        this.size--;

        if (!this.head) this.tail = null;

        return value;
    }
}

Una lista enlazada puede ser una estructura de datos muy útil en proyectos de JavaScript. Puede ayudarlo a implementar una pila, una cola y muchas otras estructuras de datos eficientes. Si necesita agregar o eliminar elementos constantemente en su aplicación, considera implementar una lista enlazada en tu proyecto de JavaScript.

Consejos y consideraciones finales para implementar una lista enlazada en tu código

Después de seguir los pasos para implementar una lista enlazada en JavaScript, existen algunos consejos y consideraciones finales importantes que debes tener en cuenta.

Primero, es crucial asegurarse de que los métodos de la lista enlazada sean eficientes. Por ejemplo, si necesitas agregar o eliminar elementos de la lista frecuentemente, debes elegir la mejor implementación de los métodos push() y pop() para mejorar la eficiencia. La misma lógica se extiende a cualquier tipo de manipulación de la lista.

En segundo lugar, es importante que controles cuidadosamente la memoria que se utiliza en tu programa. Si tienes una gran cantidad de elementos en una lista enlazada, es posible que ocasione problemas de memoria y ralentizar tu código. La solución es administrar bien la memoria y liberar objetos que ya no se estén utilizando.

Además, es posible que desees incluir algunas optimizaciones adicionales para tu lista enlazada. Por ejemplo, puedes agregar una referencia al último elemento en la lista, lo que hará que sea más sencillo insertar nuevos elementos al final de la lista.

Otra consideración importante es la depuración y el manejo de errores. Al trabajar con listas enlazadas, es probable que puedas encontrarte con algunos errores de formato o de valores inesperados. Asegúrate de incluir pruebas unitarias en tu código y manejar adecuadamente los errores que puedan surgir.

Por último, siempre es recomendable elegir una biblioteca o framework probado para implementar listas enlazadas en tu aplicación. Estas bibliotecas tienen una estructura bien definida y se prueba su código, lo que facilita mucho el proceso de implementación. Ejemplos de bibliotecas para lista enlazadas son LinkedList.js y Chain.js.

La implementación de una lista enlazada en JavaScript es un proceso bastante sencillo, sin embargo, hay algunas consideraciones importantes que debes tener en cuenta para sacarle el mayor provecho a tu código. Asegúrese de que tu lista enlazada sea eficiente, administra adecuadamente la memoria, optimiza el código, maneja errores adecuadamente y considere el uso de una biblioteca o framework para ayudarte en el proceso. Siguiendo estos consejos, podrás implementar una lista enlazada robusta y efectiva en tu código.

Otros Artículos