Las listas enlazadas combinan referencias y mutabilidad. Esto genera errores frecuentes que pueden causar comportamientos inesperados o ciclos. A continuación se describen los más habituales y cómo prevenirlos en Python.
Usar atributos que no se inicializaron deja referencias con valor indefinido (en Python, AttributeError).
class Nodo:
def __init__(self, valor):
self.valor = valor
# self.sig sin inicializar provoca AttributeError
nodo = Nodo(10)
print(nodo.sig) # ERROR
# Solución
class NodoSeguro:
def __init__(self, valor):
self.valor = valor
self.sig = None
Inicializa siempre sig en None y valida antes de acceder.
Si reasignas cabeza sin guardar el nodo previo, puedes dejar nodos inaccesibles y depender solo del recolector.
cabeza = Nodo(1)
cabeza.sig = Nodo(2)
# Si hacemos:
cabeza = cabeza.sig # se pierde el nodo con valor 1
# Forma correcta al eliminar el primero:
victima = cabeza
cabeza = cabeza.sig
victima.sig = None
Asignar sig al nodo incorrecto puede generar ciclos no deseados y recorridos infinitos.
reco.sig = reco # ERROR: ciclo inmediato
# Revisa antes de enlazar
if reco.sig is not None:
# logica normal
pass
Para detectar ciclos involuntarios, aplica el algoritmo de la tortuga y la liebre (Floyd) en pruebas.
Modificar enlaces dentro de un while sin almacenar el siguiente nodo puede corromper el recorrido.
reco = cabeza
while reco:
siguiente = reco.sig # guardar antes de mutar
# ... posibles cambios a reco.sig ...
reco = siguiente
Reutilizar el mismo nodo en dos listas causa efectos colaterales al modificar una de ellas.
nodo = Nodo(10)
lista_a.cabeza = nodo
lista_b.cabeza = nodo # ERROR: comparten el mismo nodo
Crea nodos independientes o copia los datos para evitar aliasing.
Almacenar listas o diccionarios en nodos y compartirlos sin copia genera cambios inesperados.
nodo1 = Nodo([])
nodo2 = Nodo(nodo1.valor) # referencia al mismo objeto lista
nodo1.valor.append(1)
print(nodo2.valor) # [1], efecto colateral
# Solución: copiar el dato mutable
import copy
nodo2 = Nodo(copy.deepcopy(nodo1.valor))
Romper referencias al limpiar la lista acelera la recolección y previene ciclos residuales.
def limpiar(cabeza):
while cabeza:
siguiente = cabeza.sig
cabeza.sig = None
cabeza = siguiente
None y revisa aliasing de nodos.