Pular para o conteúdo

Algoritmos e estruturas de dados · Busca e ordenação · 6 min de leitura

Algoritmos de ordenação

Merge sort, quicksort, insertion sort e o Timsort que sua linguagem já usa: complexidade, estabilidade e a pegadinha do sort() do JavaScript.

[5, 2, 4, 1] → [5, 2]: dividedivide1[5, 2, 4, 1] → [4, 1]: dividedivide2[5, 2] → [2, 5]: ordena3[4, 1] → [1, 4]: ordena4[2, 5] → [1, 2, 4, 5]5[1, 4] → [1, 2, 4, 5]6[5, 2, 4, 1][5, 2, 4, 1][5, 2][5, 2][4, 1][4, 1][2, 5][2, 5][1, 4][1, 4][1, 2, 4, 5] — intercalado[1, 2, 4, 5]intercalado

Arraste para o lado para ver o diagrama inteiro.

Dividir ao meio dá log n níveis; intercalar dois pedaços ordenados olha cada elemento uma vez por nível. Total: O(n log n), sempre.

Os principais

  • Insertion sort — O(n²), mas ótimo para listas pequenas ou quase ordenadas (O(n) se já estiver em ordem).
  • Merge sort — O(n log n) sempre e estável; usa O(n) de memória extra.
  • Quicksort — O(n log n) na média, rápido na prática e sem memória extra, mas O(n²) com pivô ruim (por exemplo, sempre o menor).
  • Heapsort — O(n log n) sempre, sem memória extra, não estável.

O que sua linguagem usa

Para objetos, Java/Kotlin (sortedBy, sortWith), Python e o V8 (Chrome, Node) usam Timsort: um merge sort que aproveita trechos já ordenados e usa insertion sort nos pedaços pequenos. É estável e O(n log n). O sort() do Swift também é estável. Raramente vale escrever o seu.

Estabilidade

Um sort estável mantém a ordem original entre itens iguais. Isso permite ordenar por vários critérios: ordene por nome e depois, de forma estável, por cidade — dentro de cada cidade os nomes continuam em ordem. Nenhum sort por comparação faz melhor que O(n log n) no pior caso.

No código: antes e depois

✗ AntesTypeScript
const notas = [10, 9, 1, 100];
notas.sort(); // [1, 10, 100, 9] — compara como texto!
✓ DepoisTypeScript
const notas = [10, 9, 1, 100];
const ordenadas = notas.toSorted((a, b) => a - b); // [1, 9, 10, 100], sem mudar notas

// Vários critérios: cidade e, empatou, nome (sort estável)
alunos.sort((a, b) => a.cidade.localeCompare(b.cidade, 'pt-BR') || a.nome.localeCompare(b.nome, 'pt-BR'));

Sem comparador, sort() converte os números em strings e compara caractere a caractere. localeCompare com "pt-BR" ordena acentos do jeito certo; toSorted devolve uma cópia.

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 do merge sort no pior caso?

    Ver a solução

    Resposta: O(n log n). São log n níveis de divisão e cada nível intercala os n elementos.

  2. Qual a complexidade do quicksort no pior caso (pivô sempre o menor elemento)?

    Ver a solução

    Resposta: O(n²). Cada partição tira só um elemento: n + (n − 1) + … + 1 ≈ n²/2 comparações.

  3. Qual algoritmo estável o Kotlin/Java (para objetos), o Python e o V8 usam por padrão?

    Ver a solução

    Resposta: Timsort. Timsort, um híbrido de merge sort e insertion sort criado por Tim Peters em 2002.

Perguntar à IA

Monte um prompt pronto sobre Algoritmos de ordenação 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 →