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

    Visualización de datos y distribución estadística para statistics.kde_random en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    statistics.kde_random: genera muestras de una KDE

    Aprende statistics.kde_random en Python para generar muestras desde una densidad estimada por kernel con ancho de banda, semillas, validación y

    Ler mais

    Tempo de leitura: 6 minutos
    13/10/2026
    Entorno Linux que representa namespaces y automatización con os.setns en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    os.setns: entra en namespaces Linux con seguridad

    Aprende os.setns en Python para entrar en namespaces Linux con permisos, validación, pruebas y limpieza segura.

    Ler mais

    Tempo de leitura: 5 minutos
    13/10/2026
    Computadora con código que representa copia de archivos con Path.copy en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    Path.copy: copia archivos y carpetas con seguridad

    Aprende Path.copy en Python para copiar archivos y directorios con seguridad, control, rendimiento y compatibilidad.

    Ler mais

    Tempo de leitura: 5 minutos
    12/10/2026
    Código en un monitor que representa acceso a memoria nativa con ctypes.memoryview_at en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    ctypes.memoryview_at: memoria nativa sin copias

    Aprende ctypes.memoryview_at en Python para acceder a memoria nativa sin copias, validar punteros y reducir riesgos.

    Ler mais

    Tempo de leitura: 7 minutos
    12/10/2026
    Código Python en pantalla representando EnumDict y enumeraciones avanzadas
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    EnumDict: personaliza Enums con validación

    Aprende EnumDict en Python para personalizar EnumType, validar miembros y crear enumeraciones avanzadas con seguridad.

    Ler mais

    Tempo de leitura: 4 minutos
    11/10/2026
    Rack de servidores que representa el balanceo de conexiones con SO_REUSEPORT_LB en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    SO_REUSEPORT_LB: reparte conexiones entre workers

    Aprende SO_REUSEPORT_LB en Python para distribuir conexiones entre workers con pruebas, portabilidad y cierre ordenado.

    Ler mais

    Tempo de leitura: 5 minutos
    11/10/2026