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 referenciasiguienteaNone.
-
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 datokeyen 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_nodoSolució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 = prevSolució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
