Pular para o conteúdo

Algoritmos e estruturas de dados · Estruturas de dados · 6 min de leitura

Tabelas hash (HashMap, Set, Dictionary)

Busca, inserção e remoção em O(1) na média: a função hash transforma a chave num índice. Como funcionam colisões, fator de carga e por que a ordem não é garantida.

chave "ana" → hash(chave)1hash(chave) → balde 3: índice 3índice 32chave "rui" → hash(chave)3balde 3 → ana → rui: mesmo índice4chave "ana"chave "ana"chave "rui"chave "rui"hash(chave) — % 8 baldeshash(chave)% 8 baldesbalde 3balde 3ana → rui — colisão: listaana → ruicolisão: lista

Arraste para o lado para ver o diagrama inteiro.

"ana" vira o índice 3 (passos 1 e 2). "rui" também cai no 3 (passo 3): é uma colisão, e o balde passa a guardar os dois (passo 4). Buscar "rui" é ir direto ao balde 3 e olhar só ali.

Como funciona

A função hash transforma a chave num número; o resto da divisão pelo número de baldes dá o índice. Buscar uma chave é calcular o hash e olhar um balde só — por isso O(1) na média, não importa se são 10 ou 10 milhões de itens.

Colisões e fator de carga

Chaves diferentes podem cair no mesmo balde. A solução clássica é uma lista por balde (o HashMap do Java vira árvore quando a lista passa de 8). Para as listas ficarem curtas, a tabela cresce quando itens ÷ baldes passa do fator de carga (0,75 no Java): dobra os baldes e redistribui tudo.

Cuidados

  • Chaves precisam de equals e hashCode coerentes (em Kotlin, data class já gera; em Swift, Hashable).
  • Não mude um objeto depois de usá-lo como chave: o hash muda e ele "some".
  • A ordem de iteração não é a de inserção, exceto em LinkedHashMap (padrão do mutableMapOf no Kotlin) e no Map do JavaScript.

No código: antes e depois

✗ AntesTypeScript
// O(pedidos × clientes): procura o cliente na lista a cada pedido
const comNome = pedidos.map((p) => ({
  ...p,
  cliente: clientes.find((c) => c.id === p.clienteId)?.nome,
}));
✓ DepoisTypeScript
// O(pedidos + clientes): indexa uma vez, consulta em O(1)
const porId = new Map(clientes.map((c) => [c.id, c.nome]));
const comNome = pedidos.map((p) => ({ ...p, cliente: porId.get(p.clienteId) }));

Com 10 mil pedidos e 10 mil clientes, a primeira versão pode fazer 100 milhões de comparações; a segunda, 20 mil operações.

Em resumo

Exercícios

Responda e confira na hora. Complexidades valem com ou sem espaços, como O(n log n).

  1. Qual a complexidade média de buscar uma chave numa tabela hash?

    Ver a solução

    Resposta: O(1). Calcula-se o hash e olha-se um balde, cuja lista é curta graças ao fator de carga.

  2. E no pior caso, se todas as chaves caírem no mesmo balde (lista encadeada)?

    Ver a solução

    Resposta: O(n). O balde vira uma lista com os n itens e a busca percorre a lista.

  3. Uma tabela com 16 baldes e fator de carga 0,75 aguenta quantos itens antes de precisar crescer?

    Ver a solução

    Resposta: 12. 16 × 0,75 = 12. Ao passar de 12 itens, a tabela dobra para 32 baldes.

Perguntar à IA

Monte um prompt pronto sobre Tabelas hash (HashMap, Set, Dictionary) na sua linguagem e no seu caso, e abra num chat gratuito.

ChatGPT Claude Perplexity

O prompt vai para o site que você escolher. Não cole senhas, tokens nem dados reais de clientes. Para Gemini e outros, copie e cole.

Referências

Continue aprendendo

Todos os temas de algoritmos e estruturas de dados →