heapq en Python: colas de prioridad

Publicado el: 28/08/2026
Tempo de leitura: 4 minutos
Crop unrecognizable person in gray sweater applying glue stick on paper while forming photo album on floor

El módulo heapq implementa heaps binarios sobre listas Python. Un heap mantiene el elemento menor en la posición cero y permite insertar o retirar prioridades en tiempo logarítmico. Esta estructura es útil en colas de prioridad, caminos mínimos, scheduling, simulaciones, procesamiento de eventos y selección de los mayores o menores valores de un flujo.

Un heap no es una lista totalmente ordenada. Solo se garantiza la relación entre padres e hijos. Recorrer la lista interna no produce elementos en orden ascendente. Usa las operaciones del módulo y trata la representación como detalle interno.

Crea un heap vacío

Un heap comienza como una lista normal.

import heapq

cola = []
heapq.heappush(cola, 5)
heapq.heappush(cola, 2)
heapq.heappush(cola, 8)
print(cola[0])

El menor valor está en cola[0], pero las demás posiciones no están completamente ordenadas.

Retira el menor elemento

heappop() elimina y devuelve la entrada menor.

while cola:
    print(heapq.heappop(cola))

Retirar de un heap vacío lanza IndexError. Comprueba la condición o trata el caso esperado.

Construye con heapify

heapify() reorganiza una lista existente en tiempo lineal.

valores = [9, 1, 7, 3, 2]
heapq.heapify(valores)

Es más eficiente que insertar cada elemento si todos ya están disponibles.

Colas de prioridad con tuplas

Las tuplas se comparan campo a campo. Un patrón común almacena prioridad y payload.

cola = []
heapq.heappush(cola, (10, "informe"))
heapq.heappush(cola, (1, "alarma"))
prioridad, tarea = heapq.heappop(cola)

Los números menores salen primero. Para prioridad mayor primero, niega valores numéricos o usa APIs de max-heap disponibles en la versión objetivo.

Empates y estabilidad

Si las prioridades empatan, Python compara el segundo campo. Tareas no comparables pueden lanzar TypeError.

from itertools import count

contador = count()
heapq.heappush(cola, (prioridad, next(contador), tarea))

El contador conserva el orden de inserción entre prioridades iguales.

No compares tareas directamente

Objetos de dominio, diccionarios y callbacks no deberían participar en el orden.

Usa (prioridad, secuencia, item) o una dataclass con campos comparables controlados.

heappushpop

heappushpop() inserta un elemento y retira el menor en una sola operación.

retirado = heapq.heappushpop(heap, nuevo_item)

Es eficiente para mantener los N mayores valores observados.

heapreplace

heapreplace() retira primero el menor y después inserta el nuevo.

antiguo = heapq.heapreplace(heap, nuevo_item)

El resultado difiere de heappushpop() cuando el nuevo valor es menor que la raíz.

Mantén los mayores N

Usa un min-heap de tamaño fijo.

limite = 100
heap = []
for valor in stream:
    if len(heap) < limite:
        heapq.heappush(heap, valor)
    elif valor > heap[0]:
        heapq.heapreplace(heap, valor)

Al final contiene los mayores valores, pero no están ordenados.

nsmallest y nlargest

nsmallest() y nlargest() seleccionan extremos.

top = heapq.nlargest(10, registros, key=lambda item: item.puntuacion)

Para N pequeño pueden ser mejores que ordenar todo. Cuando N se acerca al total, sorted() puede ser más simple y rápido.

Funciones key

Las funciones de selección aceptan key, pero heappush() no.

En un heap persistente, incluye la clave calculada en la tupla para no recalcularla.

Merge de streams ordenados

heapq.merge() combina iterables ya ordenados de forma lazy.

resultado = heapq.merge(archivo_a, archivo_b, key=extraer_clave)
for item in resultado:
    procesar(item)

Todas las entradas deben usar la misma regla de orden.

Actualiza prioridades

El módulo no ofrece decrease-key directo. Modificar una entrada dentro de la lista puede romper el heap.

Una estrategia segura inserta una entrada nueva y marca la anterior como eliminada.

ELIMINADO = object()
entradas = {}


def agregar(item, prioridad):
    if item in entradas:
        eliminar(item)
    entrada = [prioridad, next(contador), item]
    entradas[item] = entrada
    heapq.heappush(cola, entrada)


def eliminar(item):
    entrada = entradas.pop(item)
    entrada[2] = ELIMINADO

Retira entradas válidas

def retirar():
    while cola:
        prioridad, secuencia, item = heapq.heappop(cola)
        if item is not ELIMINADO:
            del entradas[item]
            return item
    raise KeyError("cola vacía")

Las entradas obsoletas consumen memoria hasta llegar a la raíz. Reconstruye el heap periódicamente si hay muchas actualizaciones.

Max-heaps

El patrón tradicional para máximos es negar prioridades numéricas.

heapq.heappush(cola, (-prioridad, secuencia, item))

No niegues valores no numéricos. Revisa también las APIs específicas disponibles en la versión mínima.

Complejidad

heappush() y heappop() son O(log n), consultar la raíz es O(1) y heapify() es O(n).

Estas garantías no incluyen comparaciones costosas o payloads grandes.

Algoritmos de grafos

Las colas de prioridad aparecen en Dijkstra, A*, Prim y simulaciones.

Sin decrease-key, inserta nuevas distancias e ignora entradas antiguas al retirarlas. En Dijkstra, valida pesos no negativos.

Scheduling de eventos

Un heap puede almacenar (instante, secuencia, callback).

heapq.heappush(eventos, (cuando, next(contador), callback))

Usa un reloj monotónico y no ejecutes callbacks largos mientras mantienes un lock.

Threads

heapq no sincroniza accesos. Varias threads necesitan lock o queue.PriorityQueue.

concurrent.futures en Python ayuda a coordinar workers, pero la cola necesita capacidad y shutdown.

Backpressure

Una cola ilimitada puede crecer hasta agotar memoria.

Define capacidad, rechazo, persistencia o descarte de baja prioridad.

Prioridades mutables

Si la prioridad depende de un atributo que cambia después de insertar, el orden se vuelve incorrecto.

Guarda una clave inmutable y actualiza mediante reinserción.

Salida ordenada

Retira repetidamente para obtener orden o usa sorted(heap) si ya no necesitas conservarlo.

Recorrer la lista interna no produce orden completo.

Persistencia

Serializar la lista interna expone detalles y entradas obsoletas.

Guarda tareas lógicas con prioridades y reconstruye mediante heapify().

Seguridad

Prioridades externas pueden monopolizar la capacidad o provocar starvation. Aplica autorización, cuotas y clases de servicio.

No ejecutes callbacks de fuentes no confiables.

Pruebas

Prueba cola vacía, empates, prioridades negativas, actualizaciones, cancelación, entradas eliminadas, top-k, volumen y concurrencia.

Compara resultados con sorted() en tests de propiedades.

Errores comunes

Los fallos frecuentes son asumir que la lista está ordenada, comparar tareas incompatibles, modificar prioridades en el lugar, confundir heapreplace() y heappushpop(), olvidar estabilidad y permitir crecimiento ilimitado.

Conclusión

heapq implementa colas de prioridad eficientes sobre listas. Usa tuplas con prioridad y secuencia, claves inmutables y lazy deletion para actualizaciones.

Consulta la documentación oficial de heapq, concurrent.futures en Python y el próximo artículo sobre bisect.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Close-up of hands using a compact black calculator on a white marble surface, displaying numbers.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    array en Python: números compactos

    Aprende array en Python para almacenar números compactos, usar typecodes, bytes, archivos, memoryview y layouts binarios portables.

    Ler mais

    Tempo de leitura: 5 minutos
    28/08/2026
    Close-up of a man with binary code projected on his face, symbolizing cybersecurity.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    struct en Python: datos binarios

    Aprende struct en Python para empacar datos binarios, controlar endianness, offsets, padding, buffers, sockets y validación segura.

    Ler mais

    Tempo de leitura: 5 minutos
    28/08/2026
    A young girl exploring a library's card catalog, symbolizes research and curiosity.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    mmap en Python: archivos en memoria

    Aprende mmap en Python para mapear archivos, buscar bytes, editar regiones, compartir memoria, alinear offsets y sincronizar accesos.

    Ler mais

    Tempo de leitura: 6 minutos
    28/08/2026
    Close-up of a hand pointing at audio editing software on a monitor in a recording studio.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    importlib.metadata: versiones y plugins

    Aprende importlib.metadata en Python para consultar versiones, requisitos, archivos, distribuciones, entry points y plugins sin importar paquetes.

    Ler mais

    Tempo de leitura: 9 minutos
    27/08/2026
    A public library bookshelf displaying a variety of books and DVDs, providing a cozy reading atmosphere.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    importlib.resources: lee archivos de paquetes

    Aprende importlib.resources en Python para leer templates y datos con Traversable, files y as_file en wheels, ZIPs y aplicaciones frozen.

    Ler mais

    Tempo de leitura: 6 minutos
    27/08/2026
    A person typing on a laptop with a Python programming book visible, capturing technology and learning.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    runpy en Python: ejecuta módulos y scripts

    Aprende runpy en Python para ejecutar módulos y scripts, controlar __main__, run_path, alter_sys, namespaces, tests y aislamiento.

    Ler mais

    Tempo de leitura: 6 minutos
    27/08/2026