heapq no Python: filas de prioridade

Publicado em: 28/08/2026
Tempo de leitura: 5 minutos
A developer typing code on a laptop with a Python book beside in an office.

O módulo heapq implementa heaps binários sobre listas Python. Um heap mantém o menor elemento na posição zero e permite inserir ou remover prioridades em tempo logarítmico. Essa estrutura é útil em filas de prioridade, algoritmos de caminho mínimo, agendamento, simulações, processamento de eventos e seleção dos maiores ou menores elementos de um conjunto.

Um heap não é uma lista totalmente ordenada. Apenas a relação entre pais e filhos é garantida. Iterar sobre a lista interna não produz os itens em ordem crescente. Use as operações do módulo e trate a representação como detalhe da estrutura.

Crie um heap vazio

Um heap é uma lista comum.

import heapq

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

O menor valor fica em fila[0], mas os demais não estão necessariamente em ordem.

Remova o menor elemento

heappop() remove e retorna o menor item.

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

Remover de um heap vazio gera IndexError. Verifique a condição ou trate o caso esperado.

Transforme uma lista com heapify

heapify() reorganiza uma lista existente em tempo linear.

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

Isso é mais eficiente que inserir todos os elementos individualmente quando os dados já estão disponíveis.

Filas de prioridade com tuplas

Tuplas são comparadas campo a campo. O padrão mais comum armazena prioridade e valor.

fila = []
heapq.heappush(fila, (10, "relatório"))
heapq.heappush(fila, (1, "alarme"))
prioridade, tarefa = heapq.heappop(fila)

Prioridades menores saem primeiro. Para prioridade maior primeiro, negue números ou use recursos de max-heap disponíveis na versão alvo.

Empates e estabilidade

Se duas prioridades forem iguais, Python tenta comparar o segundo campo. Objetos não comparáveis podem gerar TypeError.

from itertools import count

contador = count()
heapq.heappush(fila, (prioridade, next(contador), tarefa))

O contador também preserva a ordem de inserção entre prioridades iguais.

Não compare tarefas diretamente

Objetos de domínio, dicionários e callbacks não devem participar da comparação.

Use uma tupla (prioridade, ordem, item) ou uma dataclass com campos de comparação controlados.

heappushpop

heappushpop() insere um item e remove o menor em uma operação combinada.

removido = heapq.heappushpop(heap, novo_item)

Ele é eficiente para manter os N maiores elementos vistos até o momento.

heapreplace

heapreplace() remove primeiro o menor e depois insere o novo item.

antigo = heapq.heapreplace(heap, novo_item)

O resultado difere de heappushpop() quando o novo item é menor que o topo. Escolha conforme a regra do algoritmo.

Mantenha os maiores N elementos

Use um min-heap de tamanho fixo.

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

Ao final, o heap contém os maiores valores, mas não está ordenado.

nsmallest e nlargest

nsmallest() e nlargest() selecionam extremos.

top = heapq.nlargest(10, registros, key=lambda x: x.pontuacao)

Para N pequeno em relação ao total, essas funções podem ser melhores que ordenar tudo. Para N próximo do tamanho total, sorted() pode ser mais simples e rápido.

Use key com seleção

As funções de seleção aceitam key, mas heappush() não.

Para um heap persistente, inclua a chave calculada na tupla e evite recalculá-la a cada comparação.

Merge de sequências ordenadas

heapq.merge() combina iteráveis já ordenados sem carregar tudo em memória.

resultado = heapq.merge(arquivo_a, arquivo_b, key=extrair_chave)
for item in resultado:
    processar(item)

Cada entrada precisa estar ordenada pela mesma regra. O resultado é lazy.

Atualize prioridades

O módulo não oferece decrease-key direto. Alterar uma tupla dentro da lista pode quebrar o heap.

Uma estratégia segura insere uma nova entrada e marca a antiga como removida. Ao retirar itens, ignore entradas obsoletas.

REMOVIDO = object()
entradas = {}


def adicionar(item, prioridade):
    if item in entradas:
        remover(item)
    entrada = [prioridade, next(contador), item]
    entradas[item] = entrada
    heapq.heappush(fila, entrada)


def remover(item):
    entrada = entradas.pop(item)
    entrada[2] = REMOVIDO

Consuma entradas válidas

def retirar():
    while fila:
        prioridade, ordem, item = heapq.heappop(fila)
        if item is not REMOVIDO:
            del entradas[item]
            return item
    raise KeyError("fila vazia")

Entradas removidas ocupam memória até chegarem ao topo. Reconstrua o heap periodicamente se a taxa de atualização for alta.

Max-heaps

Tradicionalmente, Python oferece min-heaps e o padrão para máximos é armazenar prioridades negativas.

heapq.heappush(fila, (-prioridade, ordem, item))

Não negue valores não numéricos. Verifique também as APIs de max-heap disponíveis na versão mínima do projeto.

Complexidade

heappush() e heappop() são O(log n), consultar o topo é O(1) e heapify() é O(n).

Essas garantias não incluem o custo de comparar chaves ou manipular objetos grandes.

Dijkstra e algoritmos de grafos

Filas de prioridade aparecem em Dijkstra, A*, Prim e simulações de eventos.

Em Dijkstra sem decrease-key, insira novas distâncias e ignore entradas antigas quando forem retiradas. Valide pesos não negativos.

Agendamento de eventos

Um heap pode armazenar (instante, ordem, callback).

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

Use relógio monotônico para durações e nunca execute callbacks longos dentro de uma seção protegida por lock.

Threads

heapq não sincroniza acesso. Várias threads precisam de lock ou de queue.PriorityQueue.

O artigo de concurrent.futures no Python ajuda a coordenar workers, mas a fila ainda precisa de limites e política de shutdown.

Backpressure

Uma fila de prioridade ilimitada pode crescer até esgotar memória.

Defina capacidade, rejeição, persistência ou descarte por prioridade. Não presuma que consumidores sempre acompanharão produtores.

Objetos mutáveis

Se a prioridade depende de um atributo que muda depois da inserção, a ordem fica incorreta.

Calcule uma chave imutável no momento da entrada e atualize por reinserção quando necessário.

Ordenação final

Para obter todos os itens ordenados, retire repetidamente ou use sorted(heap) se não precisar preservar o heap.

Iterar diretamente sobre a lista interna não é ordenação.

Serialização

A lista interna pode ser serializada, mas isso expõe detalhes da implementação e entradas obsoletas.

Para persistência, salve itens lógicos e prioridades e reconstrua com heapify().

Segurança

Prioridades externas podem monopolizar a fila ou impedir trabalho importante. Aplique autorização, limites e classes de serviço.

Não execute callbacks recebidos de fontes não confiáveis.

Testes

Teste fila vazia, empates, prioridades negativas, atualizações, cancelamento, entradas removidas, top-k, grande volume e concorrência.

Compare resultados com sorted() em testes de propriedade.

Erros comuns

Os erros mais frequentes são assumir que a lista está ordenada, comparar tarefas não comparáveis, alterar prioridades no lugar, confundir heapreplace() com heappushpop(), esquecer estabilidade e permitir crescimento ilimitado.

Conclusão

heapq implementa filas de prioridade eficientes sobre listas. Use tuplas com prioridade e contador, mantenha entradas imutáveis e aplique lazy deletion para atualizações.

Consulte a documentação oficial de heapq, o guia de concurrent.futures no Python e o próximo artigo sobre bisect para listas ordenadas.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    A detailed close-up of a sleek computer keyboard with numerical keypad.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    array no Python: números compactos

    Aprenda array no Python para armazenar números compactos, trabalhar com typecodes, bytes, arquivos, memoryview e validação portátil.

    Ler mais

    Tempo de leitura: 5 minutos
    28/08/2026
    Chic portrait of a woman wearing trendy sunglasses reflecting numbers, captured in a modern setting.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    struct no Python: dados binários

    Aprenda struct no Python para empacotar dados binários, controlar endianness, offsets, padding, buffers, sockets e validação 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 Avançado
    Foto de perfil de Leandro Hirt da Academify

    mmap no Python: arquivos na memória

    Aprenda mmap no Python para mapear arquivos, buscar bytes, editar regiões, compartilhar memória, usar offsets e evitar erros de sincronização.

    Ler mais

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

    importlib.metadata: versões e plugins

    Aprenda importlib.metadata no Python para consultar versões, requisitos, arquivos, distribuições, entry points e plugins sem importar pacotes.

    Ler mais

    Tempo de leitura: 9 minutos
    27/08/2026
    Neatly arranged binders and magazines on library shelves showcasing organization.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    importlib.resources: leia arquivos de pacotes

    Aprenda importlib.resources no Python para ler templates, dados e arquivos de pacotes com Traversable, files e as_file em wheels e

    Ler mais

    Tempo de leitura: 8 minutos
    27/08/2026
    Close-up view of a computer screen displaying code in a software development environment.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    runpy no Python: execute módulos e scripts

    Aprenda runpy no Python para executar módulos e scripts, controlar __main__, run_path, alter_sys, namespaces, testes e isolamento.

    Ler mais

    Tempo de leitura: 8 minutos
    27/08/2026