Você está na página 1de 5

MC102 Introduo ` Programao de Computadores ca a ca

Mergesort e Quicksort
Felipe P.G. Bergo

Nesta aula apresentamos dois algoritmos de ordenao recursivos: mergesort e quicksort. Ambos ca tentam reduzir o problema de ordenao a dois subproblemas de tamanhos similares, levando a ca uma performance proporcional a nlog(n) em caso de sucesso.

Mergesort

Mergesort (ordenao por intercalao) divide o vetor de entrada em dois subvetores com metade ca ca do tamanho do vetor original (em caso de tamanho mpar, um dos subvetores ter um elemento a a mais que o outro). Cada um dos subvetores ordenado recursivamente. Os dois subvetores so e a intercalados em um vetor temporrio. Mergesort garante que os dois subproblemas tm tamanho a e n ca o a e 2 , mas requer alocao de memria para o vetor temporrio. O algoritmo do Mergesort dado abaixo: Algoritmo 1 MergeSort
Entrada: Sa da: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. Vetor V , ndice inicial a, ndice nal b. Vetor V , ordenado.

Se a = b, retorne V . Compute m (a+b) . 2 Ordene V [a . . . m] por MergeSort. Ordene V [m + 1 . . . b] por MergeSort. Faa i a, j m + 1 e k 0. c Aloque um vetor T [0 . . . (b a)]. Enquanto i < m + 1 ou j < b + 1 Faa c Se (i m e V [i] < V [j]) ou (j = b + 1) Ento a Faa T [k] V [i], incremente k e incremente i c Seno a Faa T [k] V [j], incremente k e incremente j. c Para i = a at b Faa e c V [i] T [i a]. Desaloque T . Retorne V .

A funo abaixo implementa o mergesort em C para ordenar vetores de inteiros: ca 1

void mergesort(int *v,int inicio,int fim) { int i,j,k,m,*t; if (inicio==fim) return; // ordenacao recursiva das duas metades m = (inicio+fim)/2; mergesort(v,inicio,m); mergesort(v,m+1,fim); // intercalacao no vetor temporario t i = inicio; j = m+1; k = 0; t = (int *) malloc(sizeof(int) * (fim-inicio+1)); while(i<m+1 || j<fim+1) { if (i==m+1) { // i passou do final da primeira metade, pegar v[j] t[k] = v[j]; j++; k++; } else if (j==fim+1) { // j passou do final da segunda metade, pegar v[i] t[k] = v[i]; i++; k++; } else if (v[i] < v[j]) { // v[i]<v[j], pegar v[i] t[k] = v[i]; i++; k++; } else { // v[j]<=v[i], pegar v[j] t[k] = v[j]; j++; k++; } } // copia vetor intercalado para o vetor original for(i=inicio;i<=fim;i++) v[i] = t[i-inicio]; free(t); }

Quicksort

O algoritmo Quicksort no requer armazenamento temporrio, mas seu procedimento de partio a a ca pode gerar subvetores de tamanhos diferentes. Quicksort escolhe um elemento pivot, e particiona o vetor de tal forma que todos os elementos menores que o pivot quem ` esquerda, e todos os a elementos maiores ou iguais ao pivot quem ` direita. As duas parties so ordenadas recursivaa co a 2

mente, e o resultado o vetor ordenado. No pior caso, quicksort leva tempo n2 . No caso mdio, e e nlog(n). O quicksort pode ser expresso pelos dois algoritmos abaixo: Algoritmo 2 QuickSort
Entrada: Sa da: Vetor V , ndice inicial a, ndice nal b. Vetor V , ordenado.

1. Se a < b 2. q Particiona(V ,a,b). 3. QuickSort(V ,a,q). 4. QuickSort(V ,q + 1,b). 5. Retorne V .

Algoritmo 3 Particiona
Entrada: Sa da: Vetor V , ndice inicial a, ndice nal b. q, ndice do ponto de partio. ca

1. Faa x V [a], i a 1 e j b + 1. c 2. Enquanto verdadeiro Faa c 3. Repita j j 1 at que V [j] x e 4. Repita i i + 1 at que V [i] x e 5. Se i < j Ento a 6. Troque V [i] com V [j]. 7. Seno retorne q = j. a

E as funes abaixo implementam o quicksort em C: co int partition(int *v,int inicio,int fim) { int x,i,j,t; x = v[inicio]; i = inicio - 1; j = fim + 1; for(;;) { do { j--; } while(v[j]>x); do { i++; } while(v[i]<x); if (i<j) { t = v[i]; v[i] = v[j]; v[j] = t; } else return j; 3

} } void quicksort(int *v,int inicio,int fim) { int q; if (inicio < fim) { q = partition(v,inicio,fim); quicksort(v,inicio,q); quicksort(v,q+1,fim); } }

Performance

Agora que os principais algoritmos de ordenao foram apresentados, mostramos uma comparao ca ca entre eles. A Figura 1a mostra comparaes entre os grcos das funes y = x (comportamento co a co linear), y = xlog(x) (comportamento log-linear) e y = x2 (comportamento quadrtico). Algoritmos a quadrticos so to piores que os lineares e log-lineares que as duas ultimas curvas cam praticaa a a mente ileg veis. A Figura 1b mostra as curvas linear e log-linear isoladamente. Note que a curva log-linear, visualmente, facilmente confundida com comportamento linear. e
40000 35000 30000 25000 20000 15000 10000 5000 0 0 50 100 N 150 200 T T Linear Log-Linear Quadratico 16000 14000 12000 10000 8000 6000 4000 2000 0 0 500 1000 N 1500 2000 Linear Log-Linear

(a)

(b)

Figura 1: Curvas t picas de tempo vs. tamanho para algoritmos lineares, log-lineares e quadrticos. a Para testar os algoritmos, foi escrito um programa que aloca um e sorteia um vetor de 5000000 elementos inteiros aleatrios. Para diversos valores de n entre 0 e 5000000, cada algoritmo ordena o o maior nmero poss de subvetores distintos com n elementos. Para os algoritmos quadrticos u vel a executamos apenas at n = 50000, por limitao de tempo. O vetor inicial foi sorteado apenas e ca uma vez e todos os algoritmos tiveram que ordenar os mesmos dados (cada algoritmo trabalhou sobre uma cpia do vetor original). Testamos duas verses do quicksort: Quick Sort 1 usa sempre o o o primeiro elemento do sub-vetor como piv. Quick Sort 2 usa a mediana dos 3 primeiros elementos. o O cdigo-fonte do programa est dispon como perf.c na pgina do curso. A Figura 2 mostra o a vel a os resultados, obtidos em um Athlon64 3200+ (2.0 GHz). Como esperado, Bubble Sort o pior dos algoritmos quadrticos. Na Figura 2a sequer conseguimos e a 4

8 7 6 T (segundos) 5 4 3 2 1 0 0 10000 20000 N

T (segundos)

Bubble Sort Selection Sort Insertion Sort Merge Sort Quick Sort 1 Quick Sort 2

0.014 0.012 0.01 0.008 0.006 0.004 0.002 0

Merge Sort Quick Sort 1 Quick Sort 2

30000

40000

50000

10000

20000 N

30000

40000

50000

(a)
2 1.8 1.6 T (segundos) 1.4 1.2 1 0.8 0.6 0.4 0.2 0 0 1e+06 2e+06 N 3e+06 4e+06 5e+06 0 0 1000 Merge Sort Quick Sort 1 Quick Sort 2 T (segundos) 0.06 0.05 0.04 0.03 0.02 0.01

(b)
Bubble Sort Selection Sort Insertion Sort Merge Sort Quick Sort 1 Quick Sort 2

2000 N

3000

4000

5000

(c)

(d)

Figura 2: Comparao da performance dos algoritmos de ordenao. ca ca

ver os resultados do Merge Sort e Quick Sort, devido ` diferena de performance entre algoritmos a c quadrticos e log-lineares. As Figuras 2b e 2c mostram Merge Sort e Quick Sort isoladamente. a Note que o uso da mediana de 3 no teve efeito no Quick Sort para dados aleatrios. Em algumas a o situaes, com dados viciados, o uso da mediana poderia evitar comportamento quadrtico do co a Quick Sort. A Figura 2d mostra a performance para n < 5000: para pequenos vetores, a escolha de um algoritmo ruim vai fazer seu programa perder apenas alguns dcimos de segundo, e razovel e e a escolher um algoritmo ruim porm mais simples de implementar. A Figura 2a deve deixar claro e que, para vetores grandes, qualquer algoritmo log-linear muito melhor que qualquer algoritmo e quadrtico. E a Figura 2b mostra que, embora Mergesort garanta log-linearidade, na prtica o a a Quicksort mais eciente. e A Tabela abaixo mostra o nmero de linhas (excluindo linhas em branco e de comentrio) usadas u a na implementao de cada algoritmo. ca Algoritmo Bubble Sort Selection Sort Insertion Sort Merge Sort Quick Sort 1 Quick Sort 2 Linhas 9 12 10 27 20 26

Você também pode gostar