Lançado · em melhoria
Algorithm
Entenda como funcionam arrays, listas ligadas, pilhas, filas e tabelas hash, quanto custa cada operação e como escolher a estrutura certa.
Uma estrutura de dados é uma forma de organizar dados na memória junto com as operações que ficam baratas nessa organização. Este tema cobre as cinco estruturas em que quase todo programa se apoia: arrays e arrays dinâmicos, listas ligadas, pilhas, filas e deques, e tabelas hash. Também explica memória contígua versus memória ligada, funções hash, colisões e fator de carga.
A estrutura escolhida decide se uma operação custa O(1) ou O(n). Montar uma fila removendo itens do início de uma lista, ou testar se um item pertence a uma lista, deixa o programa muito mais lento quando os dados crescem. Saber o que realmente são list, deque, dict e set do Python, vector, deque e unordered_map do C++, ArrayList, ArrayDeque e HashMap do Java, e Array, Map e Set do TypeScript ajuda a evitar essas armadilhas, e é a primeira coisa que as entrevistas técnicas verificam.
Comece acompanhando cada estrutura à mão em um exemplo pequeno para ver o que se move na memória. Depois implemente uma pilha, uma fila com buffer circular e um mapa hash com encadeamento separado, resuma os custos em uma tabela e meça-os com um cronômetro. Por fim, resolva exercícios em que a principal habilidade é escolher a estrutura certa.
Arrays oferecem acesso O(1) por índice e bom uso de cache; listas ligadas permitem inserir e remover em O(1) ao lado de um nó que você já tem.
Um array dinâmico cresce por um fator constante e copia seus itens, então as inserções caras ocasionais continuam custando O(1) em média.
Uma pilha remove o item mais recente e uma fila o mais antigo. Deques e buffers circulares tornam O(1) as operações nas duas pontas.
Uma tabela hash mapeia chaves para buckets e faz buscas em O(1) em média, resolve colisões com técnicas como encadeamento e cresce quando o fator de carga passa de um limite.
Um mapa hash com encadeamento separado: o hash da chave módulo o número de buckets escolhe o bucket, uma chave existente tem apenas o valor substituído e, quando o fator de carga passa de 0,75, os buckets dobram e todos os pares são reinseridos. O script também mostra uma lista usada como pilha e um deque usado como fila.
data_structures.py
from collections import deque
class HashMap:
"""Separate chaining: each bucket is a list of (key, value) pairs."""
def __init__(self, capacity=8):
self.buckets = [[] for _ in range(capacity)]
self.size = 0
def _bucket(self, key):
return self.buckets[hash(key) % len(self.buckets)]
def put(self, key, value):
bucket = self._bucket(key)
for i, (k, _) in enumerate(bucket):
if k == key:
bucket[i] = (key, value)
return
bucket.append((key, value))
self.size += 1
if self.size > 0.75 * len(self.buckets): # load factor limit
old = self.buckets
self.buckets = [[] for _ in range(2 * len(old))]
for pairs in old:
for k, v in pairs:
self._bucket(k).append((k, v))
def get(self, key, default=None):
for k, v in self._bucket(key):
if k == key:
return v
return default
stack = [1, 2, 3]
stack.append(4)
print("stack pop:", stack.pop()) # 4 (LIFO)
queue = deque([1, 2, 3])
queue.append(4)
print("queue popleft:", queue.popleft()) # 1 (FIFO)
ages = HashMap()
for name, age in [("ada", 36), ("alan", 41), ("grace", 85)]:
ages.put(name, age)
ages.put("ada", 37)
print("ada:", ages.get("ada"), "size:", ages.size) # ada: 37 size: 3
python data_structures.pySeis capítulos que levam você da instalação aos conceitos essenciais de Estruturas de dados básicas.
Tire dúvidas, compartilhe experiências e troque opiniões sobre Estruturas de dados básicas.
Ainda não há discussões. Comece a primeira.
0 comentários
Fazer login · Faça login para deixar um comentário.
Seja o primeiro a comentar.