Introducción
Las listas enlazadas son una estructura de datos fundamental que permite almacenar una colección de elementos de manera secuencial. A diferencia de los arrays, las listas enlazadas no requieren un bloque contiguo de memoria, lo que las hace más flexibles en términos de inserción y eliminación de elementos.
Conceptos Clave
- Nodo: La unidad básica de una lista enlazada. Cada nodo contiene dos partes: el dato y una referencia (o enlace) al siguiente nodo en la secuencia.
- Cabeza (Head): El primer nodo de la lista enlazada.
- Cola (Tail): El último nodo de la lista enlazada, cuya referencia al siguiente nodo es
null
.
Tipos de Listas Enlazadas
- Lista Enlazada Simple: Cada nodo apunta al siguiente nodo.
- Lista Doblemente Enlazada: Cada nodo tiene dos referencias, una al siguiente nodo y otra al nodo anterior.
- Lista Circular: El último nodo apunta de nuevo al primer nodo, formando un ciclo.
Estructura de una Lista Enlazada Simple
Nodo
Lista Enlazada
class ListaEnlazada: def __init__(self): self.cabeza = None def insertar_al_inicio(self, dato): nuevo_nodo = Nodo(dato) nuevo_nodo.siguiente = self.cabeza self.cabeza = nuevo_nodo def insertar_al_final(self, dato): nuevo_nodo = Nodo(dato) if self.cabeza is None: self.cabeza = nuevo_nodo return ultimo = self.cabeza while ultimo.siguiente: ultimo = ultimo.siguiente ultimo.siguiente = nuevo_nodo def eliminar_nodo(self, key): temp = self.cabeza if temp is not None: if temp.dato == key: self.cabeza = temp.siguiente temp = None return while temp is not None: if temp.dato == key: break prev = temp temp = temp.siguiente if temp == None: return prev.siguiente = temp.siguiente temp = None def buscar(self, key): temp = self.cabeza while temp is not None: if temp.dato == key: return True temp = temp.siguiente return False def imprimir_lista(self): temp = self.cabeza while temp: print(temp.dato, end=" -> ") temp = temp.siguiente print("None")
Explicación del Código
-
Clase
Nodo
:__init__(self, dato)
: Inicializa el nodo con el dato y establece la referenciasiguiente
aNone
.
-
Clase
ListaEnlazada
:__init__(self)
: Inicializa la lista con la cabeza (cabeza
) comoNone
.insertar_al_inicio(self, dato)
: Inserta un nuevo nodo al inicio de la lista.insertar_al_final(self, dato)
: Inserta un nuevo nodo al final de la lista.eliminar_nodo(self, key)
: Elimina el primer nodo que contiene el datokey
.buscar(self, key)
: Busca un nodo con el datokey
en la lista.imprimir_lista(self)
: Imprime todos los nodos de la lista.
Ejemplo Práctico
# Crear una lista enlazada lista = ListaEnlazada() # Insertar elementos lista.insertar_al_inicio(3) lista.insertar_al_inicio(2) lista.insertar_al_inicio(1) lista.insertar_al_final(4) # Imprimir la lista lista.imprimir_lista() # Salida: 1 -> 2 -> 3 -> 4 -> None # Buscar un elemento print(lista.buscar(3)) # Salida: True print(lista.buscar(5)) # Salida: False # Eliminar un elemento lista.eliminar_nodo(3) lista.imprimir_lista() # Salida: 1 -> 2 -> 4 -> None
Ejercicios
Ejercicio 1: Inserción en una Lista Enlazada
Instrucciones: Implementa una función insertar_despues(self, prev_dato, dato)
en la clase ListaEnlazada
que inserte un nuevo nodo después de un nodo con un dato específico (prev_dato
).
def insertar_despues(self, prev_dato, dato): temp = self.cabeza while temp is not None: if temp.dato == prev_dato: break temp = temp.siguiente if temp is None: print("El nodo con el dato", prev_dato, "no está en la lista.") return nuevo_nodo = Nodo(dato) nuevo_nodo.siguiente = temp.siguiente temp.siguiente = nuevo_nodo
Solución:
# Añadir el método a la clase ListaEnlazada ListaEnlazada.insertar_despues = insertar_despues # Crear una lista enlazada y probar la nueva función lista = ListaEnlazada() lista.insertar_al_inicio(3) lista.insertar_al_inicio(2) lista.insertar_al_inicio(1) lista.insertar_despues(2, 2.5) lista.imprimir_lista() # Salida: 1 -> 2 -> 2.5 -> 3 -> None
Ejercicio 2: Reversión de una Lista Enlazada
Instrucciones: Implementa una función revertir_lista(self)
en la clase ListaEnlazada
que revierta la lista enlazada.
def revertir_lista(self): prev = None current = self.cabeza while current is not None: next_node = current.siguiente current.siguiente = prev prev = current current = next_node self.cabeza = prev
Solución:
# Añadir el método a la clase ListaEnlazada ListaEnlazada.revertir_lista = revertir_lista # Crear una lista enlazada y probar la nueva función lista = ListaEnlazada() lista.insertar_al_inicio(3) lista.insertar_al_inicio(2) lista.insertar_al_inicio(1) lista.imprimir_lista() # Salida: 1 -> 2 -> 3 -> None lista.revertir_lista() lista.imprimir_lista() # Salida: 3 -> 2 -> 1 -> None
Conclusión
En esta sección, hemos aprendido sobre las listas enlazadas, su estructura y cómo implementarlas en Python. Hemos cubierto las operaciones básicas como inserción, eliminación y búsqueda, y hemos practicado con ejercicios para reforzar los conceptos. Las listas enlazadas son una herramienta poderosa y flexible que se utiliza en muchas aplicaciones de programación.
Curso de Estructuras de Datos
Módulo 1: Introducción a las Estructuras de Datos
- ¿Qué son las Estructuras de Datos?
- Importancia de las Estructuras de Datos en la Programación
- Tipos de Estructuras de Datos
Módulo 2: Listas
- Introducción a las Listas
- Listas Enlazadas
- Listas Doblemente Enlazadas
- Listas Circulares
- Ejercicios con Listas
Módulo 3: Pilas
- Introducción a las Pilas
- Operaciones Básicas con Pilas
- Implementación de Pilas
- Aplicaciones de las Pilas
- Ejercicios con Pilas
Módulo 4: Colas
- Introducción a las Colas
- Operaciones Básicas con Colas
- Colas Circulares
- Colas de Prioridad
- Ejercicios con Colas
Módulo 5: Árboles
- Introducción a los Árboles
- Árboles Binarios
- Árboles Binarios de Búsqueda
- Árboles AVL
- Árboles B
- Ejercicios con Árboles
Módulo 6: Grafos
- Introducción a los Grafos
- Representación de Grafos
- Algoritmos de Búsqueda en Grafos
- Algoritmos de Caminos Mínimos
- Aplicaciones de los Grafos
- Ejercicios con Grafos