Pular para o conteúdo
~/.primo-academy.sh
☰ Aulas · Estruturas de Dados · 0/14
Recomendado: essencial

Pilhas e Filas: LIFO, FIFO e Onde o Computador Usa

3 min de leitura

fonte

Pilhas e filas são restrições sobre listas. Em vez de deixar você inserir e remover em qualquer posição, cada uma só permite um padrão de acesso. Essa restrição é o que as torna previsíveis - e é exatamente isso que o computador adora.

O essencial 🟢

Pilha (stack) é LIFO: Last In, First Out. O último a entrar é o primeiro a sair. Pense numa pilha de pratos: você coloca no topo, retira do topo.

// Duas operações: push (empilha) e pop (desempilha).
const pilha = [];
pilha.push(1); // [1]
pilha.push(2); // [1, 2]
pilha.push(3); // [1, 2, 3]
pilha.pop(); // retorna 3, pilha: [1, 2]
pilha.pop(); // retorna 2, pilha: [1]
pilha.pop(); // retorna 1, pilha: []

Fila (queue) é FIFO: First In, First Out. O primeiro a entrar é o primeiro a sair. Pense numa fila de banco: você entra no fim, sai do começo.

// Duas operações: enqueue (enfileira) e dequeue (desenfileira).
// Em JS, simulamos com push + shift (shift é O(n), mas didático).
const fila = [];
fila.push(1); // [1]
fila.push(2); // [1, 2]
fila.push(3); // [1, 2, 3]
fila.shift(); // retorna 1, fila: [2, 3]
fila.shift(); // retorna 2, fila: [3]
fila.shift(); // retorna 3, fila: []
Pilha retira do topo (último a entrar). Fila retira da frente (primeiro a entrar).

Onde o computador usa cada uma:

  • Pilha: pilha de chamadas (call stack). Quando você chama uma função, ela é empilhada. Quando ela retorna, é desempilhada. Editor de texto usa pilha pra undo/redo. Navegador usa pilha pra voltar no histórico. Compilador usa pilha pra avaliar expressões (2 + 3 * 4 - empilha operandos, aplica operadores).
  • Fila: fila de impressão, fila de tarefas (task queue do event loop), fila de mensagens (RabbitMQ, SQS), BFS (busca em largura em grafos). Qualquer coisa "primeiro a chegar, primeiro a ser atendido" usa fila.

Variação importante: deque (double-ended queue). Aceita inserção e remoção nas duas pontas. Em Python, é collections.deque. Em JS, não tem nativa - você implementa com buffer circular ou usa biblioteca. Útil pra sliding window (manter uma janela dos últimos N elementos).

Aprofundamento 🟡

A pilha de chamadas é onde mora o bug de "stack overflow". Quando uma função recursiva chama ela mesma sem caso base (ou com muitos níveis de recursão), a pilha cresce até estourar. É o famoso RangeError: Maximum call stack size exceeded em JS, ou RecursionError em Python.

// Função recursiva sem caso base - estoura a pilha.
function contarParaSempre(n) {
  console.log(n);
  return contarParaSempre(n + 1); // nunca para
}
contarParaSempre(0); // crash depois de milhares de chamadas

Por isso, recursão profunda vira loop iterativo em código de produção. Exemplo clássico: travessia de árvore muito desbalanceada (BST viciada). Solução: pilha explícita (em vez da call stack) ou algoritmo morris traversal.

Por que Array.shift() em JS é lento: internamente, depois de remover o primeiro elemento, todos os outros elementos precisam "andar" uma posição pra preencher o buraco. O(n). Se você precisa de fila de verdade em JS, use uma biblioteca (ou implemente com dois ponteiros: head e tail num array, com head e tail avançando independentemente - quando o array enche, realoca).

Buffer circular (ring buffer): é como você implementa fila eficiente. Mantém um array de tamanho fixo, dois ponteiros (head e tail) que dão a volta quando chegam no fim. Inserção e remoção são O(1). Usado em sistemas embarcados, audio buffers, e o próprio event loop do Node.

Pra quem quer ir além 🔴

Algoritmo de Shunting-yard (Dijkstra, 1961) usa pilha pra converter expressão infixa (2 + 3 * 4) em pós-fixa (2 3 4 * +). A pós-fixa é trivial de avaliar com uma pilha. Compiladores reais usam variantes dessa ideia. Vale implementar uma vez na vida.

Leitura recomendada:

  • Capítulo 10.1 do Algorithms (Dasgupta et al., online) - pilhas e filas com prova de correção.
  • A página de VisuAlgo list mostra pilha, fila, deque lado a lado - clicar pra ver cada operação.

Dica: pilha e fila são tão simples que viram "bloco de Lego" pra algoritmos mais complexos. BFS usa fila. DFS (iterativo) usa pilha. Parser de expressão usa pilha. Quando travar num algoritmo, pergunte: "que estrutura de acesso restrito resolve?"

No próximo nó, vamos ver a estrutura que talvez seja a mais usada em código de produção: hash table - e por que Map/dict/object são rápidos.

// Quiz

Qual a ordem de retirada de uma pilha que recebe push(1), push(2), push(3), pop(), pop(), push(4), pop()?

Escolha uma alternativa

// recursos

// avaliação da trilha

—
ainda sem avaliações