Las colas basadas en listas enlazadas mantienen el modelo FIFO sin depender de un tamaño fijo de arreglo. Crecen y se encogen en función del número real de elementos, lo que evita reservar memoria ociosa.
final, sin necesidad de desplazar datos.Su costo principal es la gestión de referencias y la necesidad de controlar los invariantes al insertar o quitar nodos, por lo que conviene encapsular las operaciones en métodos pequeños y consistentes.
Un nodo almacena el valor y un enlace al siguiente. La cola mantiene punteros a frente y final para operar en tiempo constante:
class Nodo:
def __init__(self, dato):
self.dato = dato
self.siguiente = None
class ColaLista:
def __init__(self):
self.frente = None
self.final = None
self.cantidad = 0
Al iniciar, ambos punteros deben apuntar a None para indicar que la cola está vacía.
El encolado crea un nodo nuevo, copia el dato y ajusta el puntero final. En Python no hay que reservar memoria manualmente, pero conviene validar los invariantes.
class ColaLista:
...
def encolar(self, valor):
nuevo = Nodo(valor)
if self.cantidad == 0:
self.frente = nuevo
else:
self.final.siguiente = nuevo
self.final = nuevo
self.cantidad += 1
Cuando la cola estaba vacía, frente y final pasan a apuntar al mismo nodo.
El desencolado recupera el valor del primer nodo y avanza el puntero. Si el último elemento sale de la cola, ambos punteros vuelven a None.
class ColaLista:
...
def desencolar(self):
if self.cantidad == 0:
raise IndexError("Cola vacia")
nodo = self.frente
self.frente = nodo.siguiente
if not self.frente:
self.final = None
self.cantidad -= 1
return nodo.dato
Si la cola está vacía se lanza una excepción; también podría retornarse None dependiendo del contrato.
cantidad y operaciones fallidas ayuda a auditar el uso de la estructura.Si los nodos almacenan objetos complejos, documenta quién es dueño de liberar recursos externos.
typing.Generic permite compartir el mismo código para distintos tipos sin código duplicado.Documenta las convenciones sobre propiedad y ciclo de vida de los objetos que viajan en la cola para evitar referencias colgantes o liberaciones duplicadas.
El siguiente programa simula solicitudes que llegan a la cola, imprime su estado y realiza limpiezas antes de salir.
class Nodo:
def __init__(self, dato):
self.dato = dato
self.siguiente = None
class ColaLista:
def __init__(self):
self.frente = None
self.final = None
self.cantidad = 0
def encolar(self, valor):
nuevo = Nodo(valor)
if not self.frente:
self.frente = nuevo
else:
self.final.siguiente = nuevo
self.final = nuevo
self.cantidad += 1
def desencolar(self):
if not self.frente:
return None
nodo = self.frente
self.frente = nodo.siguiente
if not self.frente:
self.final = None
self.cantidad -= 1
return nodo.dato
def imprimir(self):
elementos = []
actual = self.frente
while actual:
elementos.append(str(actual.dato))
actual = actual.siguiente
print(f"[cola] cantidad={self.cantidad} -> {' '.join(elementos)}")
def vaciar(self):
while self.desencolar() is not None:
pass
if __name__ == "__main__":
cola = ColaLista()
for i in range(1, 4):
cola.encolar(i * 10)
cola.imprimir()
valor = cola.desencolar()
print("desencolado:", valor)
cola.imprimir()
cola.encolar(99)
cola.encolar(100)
cola.imprimir()
while cola.cantidad:
valor = cola.desencolar()
print("procesado:", valor)
cola.imprimir()
cola.vaciar()
Prueba el ejemplo con distintas secuencias para verificar que los punteros regresen a None cuando la cola se vacía y que no se pierdan nodos.