[Go to site: main page, start]

Ir al contenido principal

Listas enlazadas en Python: tutorial con ejemplos

Aprende todo lo que necesitas sobre las listas enlazadas: cuándo usarlas, sus tipos y cómo implementarlas en Python.
Actualizado 22 jul 2026  · 9 min leer

Explorar con IA

Abrir en ChatGPTAbrir en ClaudeAbrir en Perplexity

Una lista enlazada es una estructura de datos clave para organizar y gestionar información. Contiene una serie de nodos almacenados en ubicaciones aleatorias de memoria, lo que favorece una gestión eficiente de memoria. Cada nodo en una lista enlazada tiene dos componentes principales: la parte de datos y una referencia al siguiente nodo de la secuencia.

Si a primera vista te parece un concepto complejo, ¡no te preocupes!

Vamos a desgranarlo desde los fundamentos para explicar qué son las listas enlazadas, por qué las usamos y las ventajas que ofrecen.

¿Por qué listas enlazadas?

Las listas enlazadas surgieron para superar varios inconvenientes de almacenar datos en listas y arrays convencionales, como se detalla a continuación:

Facilidad de inserción y borrado

En las listas, insertar o eliminar un elemento en cualquier posición que no sea el final obliga a desplazar todos los elementos posteriores. Este proceso tiene una complejidad temporal de O(n) y puede degradar el rendimiento, sobre todo a medida que crece el tamaño de la lista. Si aún no estás familiarizado con el funcionamiento o la implementación de las listas, puedes leer nuestro tutorial sobre listas en Python.

Las listas enlazadas, en cambio, funcionan de forma distinta. Almacenan los elementos en ubicaciones de memoria no contiguas y los conectan mediante punteros a los nodos siguientes. Gracias a esta estructura, pueden añadir o eliminar elementos en cualquier posición simplemente modificando los enlaces para incluir un nuevo elemento o saltar el que se elimina.

Una vez tienes una referencia directa al nodo en el punto de inserción o borrado, la operación es O(1). Aun así, encontrar esa posición requiere un recorrido O(n), por lo que el beneficio O(1) solo aplica cuando ya tienes un puntero al nodo relevante (por ejemplo, cuando trabajas en la cabeza de la lista).

Tamaño dinámico

Las listas de Python son arrays dinámicos, lo que ofrece flexibilidad para modificar su tamaño.

Sin embargo, este proceso implica operaciones complejas, como reasignar el array a un bloque de memoria más grande. Esta reasignación es ineficiente porque hay que copiar los elementos a un bloque nuevo, pudiendo reservar más espacio del necesario en ese momento.

En cambio, las listas enlazadas pueden crecer y reducirse dinámicamente sin necesidad de reasignaciones ni redimensionamientos. Por eso son preferibles en tareas que requieren mucha flexibilidad.

Eficiencia de memoria

Las listas reservan memoria para todos sus elementos en un bloque contiguo. Si una lista debe crecer más allá de su tamaño inicial, tiene que reservar un bloque contiguo mayor y copiar todos los elementos al nuevo bloque. Este proceso es costoso e ineficiente, especialmente en listas grandes. Por otro lado, si se sobreestima el tamaño inicial, se desperdicia memoria no utilizada.

En cambio, las listas enlazadas reservan memoria por elemento. Esto permite un mejor aprovechamiento, ya que la memoria para nuevos elementos se asigna conforme se añaden.

¿Cuándo deberías usar listas enlazadas?

Aunque las listas enlazadas aportan ventajas frente a listas y arrays, como tamaño dinámico y eficiencia de memoria, también tienen limitaciones. Como hay que almacenar punteros en cada elemento para referenciar el siguiente nodo, el consumo de memoria por elemento es mayor. Además, esta estructura no permite acceso directo: para acceder a un elemento hay que recorrer secuencialmente desde el inicio, lo que conlleva una búsqueda O(n).

La decisión entre usar una lista enlazada o un array depende de las necesidades de tu aplicación. Las listas enlazadas son especialmente útiles cuando:

  • Necesitas insertar y eliminar elementos con frecuencia
  • El tamaño de los datos es impredecible o cambia a menudo
  • No es imprescindible el acceso directo a elementos
  • El conjunto de datos contiene elementos o estructuras grandes

Tipos de listas enlazadas

Existen tres tipos de listas enlazadas, cada una con ventajas para distintos escenarios:

Listas simplemente enlazadas

Image of a singly linked list

Lista simplemente enlazada

Una lista simplemente enlazada es el tipo más sencillo: cada nodo contiene datos y una referencia al siguiente nodo de la secuencia. Solo se puede recorrer en una dirección, desde la cabeza (primer nodo) hasta la cola (último nodo).

Cada nodo en una lista simplemente enlazada suele tener dos partes:

  • Datos: La información que almacena el nodo.
  • Puntero siguiente: Una referencia al siguiente nodo. El puntero del último nodo suele ser null.

Como solo se pueden recorrer en una dirección, acceder a un elemento por valor o índice exige empezar en la cabeza e ir avanzando nodo a nodo hasta encontrarlo. Esta operación es O(n), por lo que es menos eficiente en listas grandes.

Insertar y eliminar un nodo al principio es muy eficiente: O(1). En cambio, hacerlo en medio o al final requiere recorrer la lista hasta ese punto, lo que es O(n).

Por su diseño, las listas simplemente enlazadas son útiles cuando la mayoría de operaciones ocurren al inicio de la lista.

Listas doblemente enlazadas

Image of a doubly linked list

Lista doblemente enlazada

Una desventaja de las listas simplemente enlazadas es que solo se pueden recorrer en una dirección, sin posibilidad de volver al nodo anterior. Esta restricción limita operaciones que requieren navegación bidireccional.

Las listas doblemente enlazadas resuelven este problema incorporando un puntero adicional en cada nodo, lo que permite recorrer la lista en ambos sentidos. Cada nodo contiene tres elementos: los datos, un puntero al siguiente nodo y un puntero al anterior.

Listas circulares

Image of a circular linked list

Lista circular

Las listas circulares son una variante en la que el último nodo apunta de nuevo al primero, creando una estructura cíclica. A diferencia de las listas simple y doblemente enlazadas que hemos visto, aquí la lista no termina: vuelve a empezar.

Su naturaleza cíclica las hace ideales para escenarios donde hay que iterar continuamente, como juegos de mesa que pasan del último jugador al primero, o algoritmos como la planificación round-robin.

Resumen de complejidad temporal

Una comparativa rápida entre listas enlazadas y listas de Python:

Operación Lista simplemente enlazada Array/lista de Python
Acceso por índice O(n) O(1)
Búsqueda por valor O(n) O(n)
Insertar al principio O(1) O(n)
Insertar al final O(n) O(1) amortizado
Insertar en medio O(n) O(n)
Eliminar al principio O(1) O(n)
Eliminar al final O(n) O(1) amortizado

La idea principal: las listas enlazadas ganan en inserciones y borrados en la cabeza (O(1)), pero pierden en casi todo lo demás. Si no vas a añadir o quitar elementos con frecuencia al principio, probablemente te convenga más una lista de Python.

Cómo crear una lista enlazada en Python

Ahora que ya sabes qué son, por qué las usamos y sus variantes, vamos a implementarlas en Python. El cuaderno de este tutorial está disponible en este cuaderno de DataLab; si haces una copia, podrás editar y ejecutar el código. Es una gran opción si encuentras problemas al ejecutarlo en tu equipo.

Inicializar un nodo

Como vimos, un nodo es un elemento de la lista enlazada que almacena datos y una referencia al siguiente nodo. Así puedes definir un nodo en Python:

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

    def __repr__(self):
        return f"Node({self.data})"

Este código inicializa un nodo realizando dos acciones principales: al atributo "data" se le asigna el valor que representa la información del nodo. El atributo "next" representa la dirección del siguiente nodo y se establece en None para indicar que aún no enlaza con ningún otro. A medida que añadamos nodos, este atributo se actualizará para apuntar al siguiente.

Crear la clase de la lista enlazada

Después, creamos la clase de la lista enlazada. Aquí encapsularemos las operaciones para gestionar los nodos, como inserción y borrado. Empezamos inicializando la lista:

class LinkedList:
    def __init__(self):
        self.head = None  # Initialize head as None

Al establecer self.head en None, indicamos que la lista está vacía inicialmente y no hay nodos a los que apuntar. Ahora vamos a poblarla insertando nuevos nodos.

Insertar un nodo nuevo al principio

Dentro de la clase LinkedList, añadimos un método para crear un nodo nuevo y colocarlo al inicio:

    def insertAtBeginning(self, new_data):
        new_node = Node(new_data)  # Create a new node 
        new_node.next = self.head  # Next for new node becomes the   current head
        self.head = new_node  # Head now points to the new node

Cada vez que llamas a este método, se crea un nodo con los datos que indiques. Su puntero siguiente se establece en la cabeza actual, colocándolo delante de los nodos existentes. Por último, la cabeza de la lista pasa a ser el nuevo nodo.

Vamos a poblar la lista con una serie de palabras para entender mejor la inserción. Para ello, primero creamos un método para recorrer e imprimir el contenido:

    def printList(self):
        temp = self.head # Start from the head of the list
        while temp:
            print(temp.data,end=' ') # Print the data in the current node
            temp = temp.next # Move to the next node
        print()  # Ensures the output is followed by a new line

Este método imprime el contenido de nuestra lista enlazada. Ahora usemos los métodos definidos para poblarla con las palabras: "the quick brown fox".

if __name__ == '__main__':
    # Create a new LinkedList instance
    llist = LinkedList()

    # Insert each letter at the beginning using the method we created
    llist.insertAtBeginning('fox') 
    llist.insertAtBeginning('brown') 
    llist.insertAtBeginning('quick')  
    llist.insertAtBeginning('the')  

    # Now 'the' is the head of the list, followed by 'quick', then 'brown' and 'fox'

    # Print the list
    llist.printList()

Estas líneas deberían mostrar el siguiente resultado:

"the quick brown fox"

Insertar un nodo nuevo al final

Ahora crearemos un método llamado insertAtEnd dentro de la clase LinkedList para añadir un nodo al final. Si la lista está vacía, el nuevo nodo se convertirá en la cabeza. En caso contrario, se añadirá al último nodo actual. Veámoslo en la práctica:

    def insertAtEnd(self, new_data):
        new_node = Node(new_data)
        if self.head is None:
            self.head = new_node
            return
        last = self.head
        while last.next:
            last = last.next
        last.next = new_node

El método empieza creando un nuevo nodo. Después comprueba si la lista está vacía; de ser así, asigna el nuevo nodo como cabeza. Si no, recorre la lista hasta el último nodo y establece su puntero siguiente al nuevo nodo.

Incluye este método en la clase LinkedList y úsalo para añadir una palabra al final. Para ello, modifica tu función principal así:

if __name__ == '__main__':
    llist = LinkedList()

    # Insert words at the beginning
    llist.insertAtBeginning('fox')
    llist.insertAtBeginning('brown')
    llist.insertAtBeginning('quick')
    llist.insertAtBeginning('the')

    # Insert a word at the end
    llist.insertAtEnd('jumps')

    # Print the list
    llist.printList()

Observa que simplemente hemos llamado a insertAtEnd para que la palabra "jumps" aparezca al final de la lista. El código debería producir:

"the quick brown fox jumps"

Eliminar un nodo del principio

Eliminar el primer nodo es sencillo: basta con hacer que la cabeza apunte al segundo nodo. Así, el primero deja de formar parte de la lista. Para ello, añade este método en la clase LinkedList:

def deleteFromBeginning(self):
    if self.head is None:
        return "The list is empty" # If the list is empty, return this string
    self.head = self.head.next  # Otherwise, remove the head by making the next node the new head

Eliminar un nodo del final

Para eliminar el último nodo, hay que recorrer la lista hasta el penúltimo y poner su puntero siguiente a None. De este modo, el último deja de pertenecer a la lista. Copia y pega el siguiente método en tu clase LinkedList:

def deleteFromEnd(self):
    if self.head is None:
        return "The list is empty" 
    if self.head.next is None:
        self.head = None  # If there's only one node, remove the head by making it None
        return
    temp = self.head
    while temp.next.next:  # Otherwise, go to the second-last node
        temp = temp.next
    temp.next = None  # Remove the last node by setting the next pointer of the second-last node to None

Este método primero comprueba si la lista está vacía y devuelve un mensaje si lo está. Si la lista solo tiene un nodo, se elimina. En listas con varios nodos, localiza el penúltimo y actualiza su referencia siguiente a None.

Actualicemos ahora la función principal para borrar elementos al inicio y al final:

if __name__ == '__main__':
    llist = LinkedList()

    # Insert words at the beginning
    llist.insertAtBeginning('fox')
    llist.insertAtBeginning('brown')
    llist.insertAtBeginning('quick')
    llist.insertAtBeginning('the')

    # Insert a word at the end
    llist.insertAtEnd('jumps')

    # Print the list before deletion
    print("List before deletion:")
    llist.printList()

    # Deleting nodes from the beginning and end
    llist.deleteFromBeginning()
    llist.deleteFromEnd()

    # Print the list after deletion
    print("List after deletion:")
    llist.printList()

Este código imprimirá la lista antes y después del borrado, mostrando cómo funcionan las operaciones de inserción y eliminación. Deberías ver esta salida:

List before deletion:
the quick brown fox jumps 
List after deletion:
quick brown fox

Buscar un valor concreto en la lista enlazada

La última operación que veremos es la búsqueda de un valor concreto. Para ello, el método empieza en la cabeza y recorre cada nodo comprobando si sus datos coinciden con el valor buscado. Aquí tienes una implementación práctica:

def search(self, value):
    current = self.head  # Start with the head of the list
    position = 0  # Counter to keep track of the position
    while current: # Traverse the list
        if current.data == value: # Compare the list's data to the search value
            return f"Value '{value}' found at position {position}" # Print the value if a match is found
        current = current.next
        position += 1
    return f"Value '{value}' not found in the list" 

Para buscar valores en la lista que hemos creado, actualiza tu función principal para incluir el método de búsqueda que acabamos de añadir:

if __name__ == '__main__':
    llist = LinkedList()

    # Insert words at the beginning
    llist.insertAtBeginning('fox')
    llist.insertAtBeginning('brown')
    llist.insertAtBeginning('quick')
    llist.insertAtBeginning('the')

    # Insert a word at the end
    llist.insertAtEnd('jumps')

   # Print the list before deletion
    print("List before deletion:")
    llist.printList()

    # Deleting nodes from beginning and end
    llist.deleteFromBeginning()
    llist.deleteFromEnd()

    # Print the list after deletion
    print("List after deletion:")
    llist.printList()
    
        # Search for 'quick' and 'lazy' in the list
    print(llist.search('quick'))  # Expected to find
    print(llist.search('lazy'))   # Expected not to find

Este código producirá la siguiente salida:

List before deletion:
the quick brown fox jumps 
List after deletion:
quick brown fox 
Value 'quick' found at position 0
Value 'lazy' not found in the list

La palabra "quick" se ha localizado correctamente porque está en la primera posición de la lista. En cambio, "lazy" no forma parte de la lista, por eso no se encuentra.

Reflexiones finales

¡Enhorabuena por llegar hasta aquí! Ahora tienes una base sólida sobre las listas enlazadas: su estructura, tipos, cómo añadir y eliminar elementos y cómo recorrerlas.

Pero el viaje no acaba aquí. Las listas enlazadas son solo la puerta de entrada al mundo de las estructuras de datos y los algoritmos. Aquí tienes algunos posibles próximos pasos para profundizar:

Crea tu propio proyecto

Explora aplicaciones prácticas integrando listas enlazadas en un proyecto de programación o ciencia de datos. Se usan para desarrollar sistemas de archivos, construir tablas hash e incluso crear sistemas de navegación GPS y juegos de mesa. Para empezar con tus propios proyectos, echa un vistazo a nuestros proyectos de ciencia de datos gratuitos y guiados, donde aprenderás a resolver problemas reales en Python, R y SQL.

Aprende sobre estructuras de datos y algoritmos

Aprender otras estructuras como árboles, pilas y colas es el siguiente paso natural desde las listas enlazadas. Se basan en los mismos principios y te ayudan a resolver un abanico más amplio de problemas de forma eficiente. Por ejemplo, los árboles y los árboles binarios de búsqueda amplían el concepto de lista enlazada a una forma jerárquica, permitiendo que cada nodo se conecte con múltiples elementos.

Si estos conceptos te suenan lejanos, ¡tranquilo! Datacamp tiene un curso completo de estructuras de datos y algoritmos en Python que los explica en detalle. Primero verás pilas, árboles, tablas hash, colas y grafos. Después aprenderás algoritmos de búsqueda y ordenación, que te ayudarán a programar y resolver problemas con más eficiencia.

Explora conceptos avanzados de listas enlazadas

En este tutorial hemos implementado listas simplemente enlazadas, con operaciones como inserción, borrado y recorrido.

Puedes ir un paso más allá aprendiendo a implementar listas doblemente enlazadas y circulares. Las skip lists son otra extensión que permite acelerar las búsquedas facilitando accesos más rápidos a los elementos.

Conocer estas estructuras avanzadas llevará tus habilidades técnicas al siguiente nivel y mejorará tu capacidad de programación, preparándote para retos más complejos en ciencia de datos, desarrollo de software e ingeniería de machine learning.

Si prefieres una introducción más amigable antes de abordar estos temas, explora nuestro itinerario de habilidades Python Programming. Ofrece una serie de cursos con los fundamentos del lenguaje.


Natassha Selvaraj's photo
Author
Natassha Selvaraj
LinkedIn
Twitter

Natassha es una consultora de datos que trabaja en la intersección de la ciencia de datos y el marketing. Cree que los datos, cuando se utilizan sabiamente, pueden inspirar un enorme crecimiento para las personas y las organizaciones. Como profesional de datos autodidacta, a Natassha le encanta escribir artículos que ayuden a otros aspirantes a entrar en el sector de la ciencia de datos. Sus artículos en su blog personal, así como en publicaciones externas, acumulan una media de 200.000 visitas mensuales.

Temas

¡Sigue aprendiendo Python!

programa

Fundamentos de Datos en Python

28 h
Desarrolla tus habilidades con los datos, descubre cómo manipularlos y visualizarlos, y aplica análisis avanzados para tomar decisiones basadas en datos.
Ver detallesRight Arrow
Iniciar Curso
Ver másRight Arrow
Relacionado

Tutorial

Guía completa de listas vacías en Python

Aprenda las principales operaciones con listas y los casos de uso de las listas vacías en Python.
Adel Nehme's photo

Adel Nehme

Tutorial

Tutorial y ejemplos de funciones y métodos de listas en Python

Aprende sobre las funciones y métodos de las listas de Python. ¡Sigue ahora los ejemplos de código para list() y otras funciones y métodos de Python!
Abid Ali Awan's photo

Abid Ali Awan

Tutorial

Tutorial de Estructuras de Datos en Python

Introdúcete en las estructuras de datos de Python: aprende más sobre tipos de datos y estructuras de datos primitivas y no primitivas, como cadenas, listas, pilas, etc.
Sejal Jaiswal's photo

Sejal Jaiswal

Tutorial

Tutorial sobre cómo concatenar cadenas en Python

Aprende varios métodos para concatenar cadenas en Python, con ejemplos que ilustran cada técnica.
DataCamp Team's photo

DataCamp Team

Tutorial

Tutorial de Python sobre conjuntos y teoría de conjuntos

Aprende sobre los conjuntos en Python: qué son, cómo crearlos, cuándo usarlos, funciones incorporadas y su relación con las operaciones de la teoría de conjuntos.
DataCamp Team's photo

DataCamp Team

Tutorial

Método index() de Python List explicado con ejemplos

Aprende a utilizar la función index() de Python para encontrar la posición de elementos en listas.
Sejal Jaiswal's photo

Sejal Jaiswal

Ver MásVer Más