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.
Arraste para girar. Role ou faça pinça para dar zoom.
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.
| Método | Comparações | Memória extra |
|---|---|---|
| Insertion sort | em geral cerca de n²/4, no pior caso cerca de n²/2 | nenhuma; estável |
| Merge sort | cerca de n log₂ n, sempre | uma segunda lista de n valores; estável |
| Quicksort | em 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 |
| dividir para conquistar | Dividir um problema, resolver as partes do mesmo jeito, combinar os resultados |
| intercalar | Combinar duas listas ordenadas pegando sempre o menor valor da frente |
| merge sort | Cortar 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 |
| particionamento | Rearranjar para que os valores menores fiquem antes do pivô e o resto depois |
| quicksort | Particionar em torno de um pivô e depois ordenar cada lado |
| ordenação estável | Valores iguais mantêm a ordem original |
| no lugar (in place) | Ordena dentro da lista original com pouca memória extra |
- Quantas comparações são necessárias para intercalar [1, 4, 7] e [2, 3, 8]?
- Quantas comparações são necessárias para intercalar [1, 2, 3] e [4, 5, 6]?
- Uma lista de 16 valores é cortada ao meio até cada parte ter um valor. Quantos níveis de corte existem?
- 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
- 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
- O quicksort com o último valor como pivô roda na lista já ordenada [1, 2, 3, 4, 5]. Quantas comparações ele faz?
- Qual método precisa de uma segunda lista do tamanho da entrada?
- Merge sort
- Quicksort
- Insertion sort
- Quem propôs o merge sort em 1945?
- Tony Hoare
- John von Neumann
- Ada Lovelace
- Euclides
- 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
- 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
- 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)?
- 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