Escolhendo uma estrutura de dados
Entre 1023 chaves, uma busca linear por uma chave ausente faz 1023 comparações, a busca binária faz 10, e uma tabela hash com 1023 baldes fez no máximo 6 no laboratório.
Comece pelas perguntas que você vai fazer
Nenhuma estrutura é a melhor em tudo. Cada uma deixa algumas operações baratas tornando outras caras, então o jeito de escolher é listar o que o seu programa vai fazer com mais frequência. O 6.006 do MIT divide as possibilidades em duas interfaces. Uma sequência guarda os itens numa ordem que você decide (primeiro, segundo, terceiro), e você pede os itens pela posição. Um conjunto (set) guarda os itens por chave, e você pergunta se uma chave está lá, ou qual é a menor chave, ou a próxima depois de uma chave dada. Um conjunto sem as perguntas de ordem se chama dicionário.
Algumas situações comuns e a resposta de costume:
- Ler itens pela posição, acrescentar no fim: um array dinâmico (um array de JavaScript).
- Histórico de desfazer, parênteses que combinam, busca em profundidade: uma pilha, que é um array usado só no fim.
- Trabalhos tratados na ordem de chegada, busca em largura: uma fila, com índice head ou buffer circular em vez de shift num array comprido.
- Procurar coisas por nome ou id: uma tabela hash, que em JavaScript quer dizer Map ou Set.
- Manter chaves ordenadas enquanto insere e apaga, pedir a próxima chave: uma árvore binária de busca balanceada.
- Muitas inserções e remoções num ponto que você já tem nas mãos: uma lista encadeada.
A mesma busca em cinco estruturas
O laboratório abaixo guarda as mesmas chaves de cinco jeitos e conta as comparações necessárias para achar uma delas. As chaves são 15, 127 ou 1023 números inteiros aleatórios. O array desordenado usa busca linear. O array ordenado usa busca binária. A árvore balanceada foi construída inserindo primeiro as chaves do meio, então é a mais baixa possível. A outra árvore foi construída com as chaves em ordem crescente, então é uma cadeia. A tabela hash tem tantos baldes quanto chaves e conta 1 para calcular h(k).
Arraste para girar. Role ou faça pinça para dar zoom.
Com 15 chaves as diferenças são pequenas: a busca linear precisa de 8 comparações em média e a busca binária de cerca de 3.3. Com 1023 chaves, não. A busca linear tem média de 512 e precisa de 1023 para uma chave ausente, enquanto a busca binária e a árvore balanceada nunca precisam de mais de 10. A árvore em cadeia é tão ruim quanto a busca linear. A tabela hash fica entre 2.3 e 2.5 em média em todos os tamanhos, porque as cadeias dela continuam curtas, e neste laboratório o pior caso dela com 1023 chaves foi 6. É por isso que o Map é a escolha padrão para buscas, e por isso as estruturas ordenadas só compensam quando você também precisa de ordem.
| Por posição | Pegar o item i | Inserir ou apagar na frente |
|---|---|---|
| Array dinâmico | 1 | n |
| Lista encadeada | n | 1 |
| Array ordenado | 1 | n |
| Por chave | Achar | Inserir | Próxima chave |
|---|---|---|---|
| Array ou lista | n | n | n |
| Array ordenado | log n | n | log n |
| Tabela hash | 1 em média | 1 em média | n |
| BST balanceada | log n | log n | log n |
Cada célula destas duas tabelas é a taxa de crescimento do custo para n itens, seguindo as tabelas das notas de aula 2, 4 e 7 do MIT. Tabelas hash e árvores de busca só aparecem na segunda tabela porque trabalham por chave, não por posição. Num array desordenado ou numa lista, inserir uma chave custa n porque é preciso primeiro conferir se ela já não está lá. O array ordenado acha rápido, mas precisa mover valores para abrir espaço para uma chave nova.
Map ou objeto?
Programas em JavaScript muitas vezes usam um objeto comum como dicionário, escrevendo prices["apple"]. O MDN lista motivos para preferir o Map quando as chaves vêm dos dados: um objeto tem um protótipo, então contém chaves padrão que podem colidir com as suas; um Map pode usar qualquer valor como chave, não só strings e símbolos; o tamanho dele é uma propriedade só, map.size; e ele é percorrido na ordem de inserção. Os objetos continuam sendo a escolha natural para registros com um conjunto fixo de campos com nome.
- 1953: O memorando de H. P. Luhn na IBM sugere o hashing em baldes com encadeamento.
- Por volta de 1956: A IPL de Newell, Shaw e Simon traz as listas encadeadas.
- 1957: Bauer e Samelson pedem a patente do método da pilha; o Fortran é lançado com arrays.
- 1962: Adelson-Velsky e Landis publicam a árvore AVL, a primeira árvore de busca balanceada.
- 2015: O ECMAScript 2015 acrescenta Map e Set ao JavaScript.
- Uma busca linear por uma chave ausente entre 1023 chaves faz quantas comparações?
- A busca binária entre 1023 chaves ordenadas faz no máximo quantas comparações?
- Busca linear em 15 chaves: qual é o número médio de comparações sobre todas as 15 chaves?
- Uma BST construída com 127 chaves inseridas em ordem crescente: quantas comparações para a maior chave?
- Um editor de texto precisa de Desfazer. Qual estrutura serve?
- Fila
- Pilha
- Tabela hash
- Array ordenado
- Um servidor de impressão precisa tratar os trabalhos na ordem em que chegam. Qual estrutura serve?
- Fila
- Pilha
- BST
- Lista encadeada usada como pilha
- Você precisa procurar o registro de um usuário pelo id muitas vezes por segundo. Qual é a escolha de costume em JavaScript?
- Um array percorrido com um laço
- Um Map com o id como chave
- Uma pilha
- Uma lista encadeada
- Você precisa manter as chaves em ordem crescente enquanto insere e apaga, e pergunta muitas vezes pela próxima chave maior. O que serve melhor?
- Tabela hash
- BST balanceada
- Fila
- Array desordenado
- Nos termos do MIT 6.006, um conjunto sem as operações de ordem se chama
- uma sequência
- um dicionário
- uma pilha
- uma fila
- Segundo o MDN, por que um objeto comum pode ser arriscado como dicionário para chaves que vêm dos dados?
- Objetos não conseguem guardar strings
- O protótipo dele traz chaves padrão que podem colidir com as suas
- Objetos são sempre mais lentos que arrays
- Objetos esquecem valores depois de um segundo
- Escolha pelas operações que você vai fazer com mais frequência.
- Sequência: array, lista encadeada, pilha, fila. Conjunto: tabela hash, BST.
- Para 1023 chaves: busca linear até 1023 comparações, busca binária e árvore balanceada até 10.
- O Map é o dicionário de costume em JavaScript; use uma árvore balanceada quando também precisar de ordem.
Fontes deste curso (11)
- MIT OpenCourseWare 6.006 Introduction to Algorithms, Spring 2020 (Demaine, Ku, Solomon)
- lecture notes 2 Data Structures (interface vs data structure, Sequence and Set interfaces, stack = insert_last/delete_last, queue = insert_last/delete_first, array, linked list, dynamic array, amortized Θ(1) append)
- 4 Hashing (chaining, pigeonhole collisions, chain length n/m)
- 6 Binary Trees Part 1 (height, traversal order, O(h) operations) and 7 Binary Trees Part 2: AVL (Adelson-Velsky and Landis, 1962) at ocw.mit.edu/courses/6-006-introduction-to-algorithms-spring-2020/pages/lecture-notes
- MDN Web Docs, Array.prototype.shift (shifts all values left by 1)
- Array.prototype.unshift, Map (insertion order, Map vs Object, spec requires sublinear average access) and Set (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects)
- ECMAScript 2025 Language Specification (tc39.es/ecma262)
- 24.1 Map Objects and 24.2 Set Objects ("must be implemented using either hash tables or other mechanisms that, on average, provide access times that are sublinear on the number of elements")
- Array.prototype.shift steps (Repeat, while k < len: move element k to k - 1)
- D. E. Knuth, The Art of Computer Programming vol. 3 (2nd ed. 1998) section 6.4 History (H. P. Luhn, IBM internal memorandum January 1953, hashing with chaining; digit pairs added mod 10, 31415926 -> 4548) via gwern.net copy, and IEEE Spectrum, "Hans Peter Luhn and the Birth of the Hashing Algorithm" (2018)
- "A brief history of the stack", SIGCIS (sigcis.org/files/A brief history.pdf: Bauer and Samelson applied for the patent in 1957, US 3,047,228 granted July 31, 1962; IPL list processing by Newell, Simon and Shaw at RAND 1956) and Wikipedia, Information Processing Language (Newell, Shaw, Simon, RAND and Carnegie Institute of Technology, about 1956).
Data de verificação: 2026-10-18