edubun
Português

Ordenação 2: merge sort e quicksort

Ordenar um milhão de valores comparando todos os pares leva cerca de 500 bilhões de comparações; o merge sort precisa de cerca de 20 milhões.

Divida o problema, resolva as metades

Os métodos da unidade anterior trabalham com a lista inteira de uma vez e pagam por isso com cerca de n² comparações. Os dois métodos desta unidade usam outro plano, chamado dividir para conquistar. Divida a lista em partes menores, ordene cada parte com o mesmo método e depois combine as partes ordenadas. A divisão continua até uma parte ter um valor ou nenhum, e uma lista de um valor já está ordenada. Como o método chama a si mesmo em listas menores, ele é recursivo (a unidade 6 trata da recursão em detalhe).

Merge sort: o trabalho está na intercalação

O merge sort (ordenação por intercalação) corta a lista ao meio, ordena a metade esquerda, ordena a metade direita e intercala as duas metades ordenadas numa só. A parte esperta é a intercalação. Duas listas ordenadas podem ser combinadas olhando só os valores da frente. Compare as duas frentes, anote o menor e passe para o seguinte. Repita até uma lista ficar vazia e depois copie o que sobrou da outra. Intercalar [1, 4, 7] e [2, 3, 8] dá 1 (1 contra 2), 2 (4 contra 2), 3 (4 contra 3), 4 (4 contra 8), 7 (7 contra 8), e então o 8 é copiado: 5 comparações para 6 valores. Uma intercalação de duas listas com n valores no total nunca precisa de mais de n − 1 comparações.

function merge(left, right) {
  const out = [];
  let i = 0, j = 0;
  while (i < left.length && j < right.length) {
    if (right[j] < left[i]) out.push(right[j++]);
    else out.push(left[i++]);
  }
  return out.concat(left.slice(i), right.slice(j));
}

function mergeSort(a) {
  if (a.length <= 1) return a;          // já está ordenada
  const mid = Math.floor(a.length / 2);
  return merge(mergeSort(a.slice(0, mid)), mergeSort(a.slice(mid)));
}

Por que isso é rápido? Imagine os cortes ao meio como níveis. Uma lista de 8 valores se divide em 2 listas de 4, depois 4 listas de 2, depois 8 listas de 1: três níveis, porque 8 pode ser cortado ao meio 3 vezes. Em cada nível, todas as intercalações juntas tocam cada valor uma vez, então um nível custa no máximo cerca de n comparações. Com log₂ n níveis, o total fica em torno de n log₂ n. Para um milhão de valores isso dá cerca de 20 milhões de comparações, contra cerca de 500 bilhões dos métodos que comparam par a par. Dividida como [38, 27, 43, 3] e [9, 82, 10], como no laboratório, a lista [38, 27, 43, 3, 9, 82, 10] leva 14 comparações; o código acima a divide em 3 e 4 e leva 13.

O preço é a memória. A intercalação precisa de um lugar para escrever a saída, então o merge sort usa uma segunda lista do tamanho da entrada. O merge sort também é estável: valores que são iguais na comparação mantêm a ordem original, porque a intercalação pega da lista esquerda quando as frentes são iguais. Isso importa quando você ordena uma tabela por uma coluna depois da outra, por exemplo por cidade e depois por nome.

Carregando

Arraste para girar. Role ou faça pinça para dar zoom.

O merge sort sombreia a parte sendo intercalada; o quicksort marca o pivô em violeta. Aumente o número de valores para 40 e compare os contadores com os do insertion sort.

Quicksort: divida em torno de um pivô

O quicksort divide a lista de outro jeito. Ele escolhe um valor, o pivô, e rearranja a lista para que tudo o que é menor que o pivô venha antes dele e todo o resto venha depois. Esse passo se chama particionamento. Agora o pivô está no lugar final, e os dois lados podem ser ordenados separadamente com o mesmo método. Não é preciso intercalar nada depois, porque todo valor da esquerda já é menor que todo valor da direita.

O laboratório usa uma versão comum dos livros didáticos, que pega o último valor de cada parte como pivô. Em [5, 1, 4, 2, 8], o pivô 8 é comparado com os outros quatro valores, todos menores, então o 8 fica no fim. A parte seguinte, [5, 1, 4, 2], usa o pivô 2: só o 1 é menor, então depois de duas trocas a lista fica [1, 2, 4, 5, 8]. Mais uma comparação resolve [4, 5]. Total: 8 comparações e 2 trocas.

Quando o pivô cai perto do meio, cada divisão corta o problema ao meio e o quicksort leva cerca de n log₂ n comparações, como o merge sort. Ele também trabalha dentro da lista original, sem uma segunda cópia. Mas um pivô ruim atrapalha. Se a lista já está ordenada e o pivô é sempre o último valor, cada divisão separa só um valor, e o quicksort volta a cerca de n²/2 comparações: 10 para [1, 2, 3, 4, 5], o mesmo que o selection sort. As bibliotecas de verdade evitam isso escolhendo o pivô com mais cuidado, por exemplo ao acaso ou como o do meio entre três valores de amostra.

ContextoOs dois métodos têm origem conhecida. O merge sort foi proposto por John von Neumann em 1945, quando os primeiros computadores de programa armazenado estavam sendo projetados. O quicksort veio de Tony Hoare, um estudante britânico na Universidade Estatal de Moscou em 1959. Ele recebeu uma oferta para trabalhar com tradução automática do russo para o inglês e, como o dicionário ficava em fita magnética, as palavras de cada frase primeiro precisavam ser postas em ordem alfabética. A primeira ideia dele levava um tempo proporcional ao quadrado do comprimento da frase; a segunda virou o quicksort. Ele o publicou em 1961.
MétodoComparaçõesMemória extra
Insertion sortem geral cerca de n²/4, no pior caso cerca de n²/2nenhuma; estável
Merge sortcerca de n log₂ n, sempreuma segunda lista de n valores; estável
Quicksortem geral cerca de n log₂ n, no pior caso cerca de n²/2 (pivôs ruins)pouca; as versões comuns não são estáveis
Algum método de ordenação por comparação consegue superar n log₂ n? Não. Um método que só aprende comparando pares precisa conseguir distinguir todas as n! ordens iniciais possíveis, e cada comparação tem dois resultados, então o pior caso exige pelo menos log₂(n!) comparações, que cresce como n log₂ n. Para 10 valores esse limite é de 22 comparações.
dividir para conquistarDividir um problema, resolver as partes do mesmo jeito, combinar os resultados
intercalarCombinar duas listas ordenadas pegando sempre o menor valor da frente
merge sortCortar ao meio, ordenar cada metade, intercalar: cerca de n log₂ n comparações
pivôO valor em torno do qual o quicksort divide a lista
particionamentoRearranjar para que os valores menores fiquem antes do pivô e o resto depois
quicksortParticionar em torno de um pivô e depois ordenar cada lado
ordenação estávelValores iguais mantêm a ordem original
no lugar (in place)Ordena dentro da lista original com pouca memória extra
  1. Quantas comparações são necessárias para intercalar [1, 4, 7] e [2, 3, 8]?
  2. Quantas comparações são necessárias para intercalar [1, 2, 3] e [4, 5, 6]?
  3. Uma lista de 16 valores é cortada ao meio até cada parte ter um valor. Quantos níveis de corte existem?
  4. Mais ou menos quantas comparações o merge sort faz com um milhão de valores?
    • cerca de 20
    • cerca de 20 milhões
    • cerca de 500 bilhões
    • exatamente um milhão
  5. Depois do particionamento, onde está o pivô?
    • Na sua posição final ordenada
    • Na frente
    • No fim
    • Em qualquer lugar; ele se move de novo depois
  6. O quicksort com o último valor como pivô roda na lista já ordenada [1, 2, 3, 4, 5]. Quantas comparações ele faz?
  7. Qual método precisa de uma segunda lista do tamanho da entrada?
    • Merge sort
    • Quicksort
    • Insertion sort
  8. Quem propôs o merge sort em 1945?
    • Tony Hoare
    • John von Neumann
    • Ada Lovelace
    • Euclides
  9. Que problema levou Tony Hoare ao quicksort?
    • Ordenar as palavras de uma frase para um dicionário em fita magnética
    • Ordenar livros de biblioteca
    • Classificar páginas web
    • Ordenar cheques bancários
  10. Por que o merge sort é chamado de estável?
    • Valores iguais mantêm a ordem original
    • Ele nunca trava
    • Leva sempre o mesmo tempo
    • Não usa memória extra
  11. Qual é o menor número possível de comparações no pior caso para qualquer ordenação por comparação de 10 valores (log₂ 10!, arredondado para cima)?
Pontos-chave
  • Dividir para conquistar: dividir, resolver as partes, combinar.
  • Merge sort: sempre cerca de n log₂ n comparações, precisa de memória extra, estável.
  • Quicksort: particiona em torno de um pivô; rápido em média, cerca de n²/2 com pivôs ruins.
  • Um milhão de valores: cerca de 20 milhões de comparações em vez de 500 bilhões.
  • Nenhuma ordenação por comparação consegue superar cerca de n log₂ n no pior caso.
Fontes deste curso (11)
  • MIT OpenCourseWare 6.006 Introduction to Algorithms, Spring 2020 (Demaine, Ku, Solomon)
  • lecture notes 1 Introduction, 3 Sorting, 9 Breadth-First Search, 10 Depth-First Search (ocw.mit.edu/courses/6-006-introduction-to-algorithms-spring-2020/pages/lecture-notes) and Fall 2011 lecture 13 BFS notes (ocw.mit.edu/courses/6-006-introduction-to-algorithms-fall-2011)
  • Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms (MIT Press)
  • with the CLRS-based Khan Academy algorithms unit by Thomas Cormen and Devin Balkcom of Dartmouth (khanacademy.org/computing/computer-science/algorithms: binary search, selection sort analysis, merge sort, quicksort overview and analysis)
  • MacTutor History of Mathematics, Al-Khwarizmi (mathshistory.st-andrews.ac.uk/Biographies/Al-Khwarizmi: word algorithm from the Latin title Algoritmi de numero Indorum)
  • D. E. Joyce, Euclid's Elements Book VII Propositions 1 and 2 (mathcs.clarku.edu/~djoyce/elements/bookVII)
  • Wolfram MathWorld, Merge Sort (mathworld.wolfram.com/MergeSort.html: proposed by John von Neumann in 1945, after Knuth 1998 p. 159)
  • Stanford CS "Tony Hoare: Quicksort" (cs.stanford.edu/people/eroberts/courses/soco/projects/2008-09/tony-hoare/quicksort.html: devised while a student at Moscow State University for Russian-English machine translation with a tape dictionary, programmed in Algol 60 and published 1961; the year 1959 from the Wikipedia Quicksort article and its cited sources)
  • Bodleian Libraries, Ada Lovelace (blogs.bodleian.ox.ac.uk/adalovelace: 1843 paper, Note G Bernoulli numbers)
  • Fourmilab text of Menabrea's Sketch with Lovelace's notes (fourmilab.ch/babbage/sketch.html)
  • Seven Bridges of Konigsberg (Euler 1736) and Tower of Hanoi (Edouard Lucas, 1883) checked against the Wikipedia articles and their cited sources.

Data de verificação: 2026-10-17