Vous êtes sur la page 1sur 5

MC102 Introdu c ao ` a Programa c ao de Computadores

Mergesort e Quicksort
Felipe P.G. Bergo

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

Mergesort

Mergesort (ordena c ao por intercala c ao) divide o vetor de entrada em dois subvetores com metade do tamanho do vetor original (em caso de tamanho mpar, um dos subvetores ter a um elemento a mais que o outro). Cada um dos subvetores e ordenado recursivamente. Os dois subvetores s ao intercalados em um vetor tempor ario. Mergesort garante que os dois subproblemas t em tamanho n c ao de mem oria para o vetor tempor ario. O algoritmo do Mergesort e dado 2 , mas requer aloca 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 . b) Compute m (a+ 2 . Ordene V [a . . . m] por MergeSort. Ordene V [m + 1 . . . b] por MergeSort. Fa ca i a, j m + 1 e k 0. Aloque um vetor T [0 . . . (b a)]. Enquanto i < m + 1 ou j < b + 1 Fa ca Se (i m e V [i] < V [j ]) ou (j = b + 1) Ent ao Fa ca T [k ] V [i], incremente k e incremente i Sen ao Fa ca T [k ] V [j ], incremente k e incremente j . Para i = a at e b Fa ca V [i] T [i a]. Desaloque T . Retorne V .

A fun c ao abaixo implementa o mergesort em C para ordenar vetores de inteiros: 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 n ao requer armazenamento tempor ario, mas seu procedimento de parti c ao 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 ` a esquerda, e todos os elementos maiores ou iguais ao pivot quem ` a direita. As duas parti c oes s ao ordenadas recursiva2

mente, e o resultado e o vetor ordenado. No pior caso, quicksort leva tempo n2 . No caso m edio, 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 parti c ao.

1. Fa ca x V [a], i a 1 e j b + 1. 2. Enquanto verdadeiro Fa ca 3. Repita j j 1 at e que V [j ] x 4. Repita i i + 1 at e que V [i] x 5. Se i < j Ent ao 6. Troque V [i] com V [j ]. 7. Sen ao retorne q = j .

E as fun c oes abaixo implementam o quicksort em C: 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 ordena c ao foram apresentados, mostramos uma compara c ao entre eles. A Figura 1a mostra compara c oes entre os gr acos das fun c oes y = x (comportamento linear), y = xlog (x) (comportamento log-linear) e y = x2 (comportamento quadr atico). Algoritmos quadr aticos s ao t ao piores que os lineares e log-lineares que as duas u ltimas curvas cam praticamente ileg veis. A Figura 1b mostra as curvas linear e log-linear isoladamente. Note que a curva log-linear, visualmente, e facilmente confundida com comportamento linear.
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 quadr aticos. Para testar os algoritmos, foi escrito um programa que aloca um e sorteia um vetor de 5000000 elementos inteiros aleat orios. Para diversos valores de n entre 0 e 5000000, cada algoritmo ordena o maior n umero poss vel de subvetores distintos com n elementos. Para os algoritmos quadr aticos executamos apenas at e n = 50000, por limita c ao de tempo. O vetor inicial foi sorteado apenas uma vez e todos os algoritmos tiveram que ordenar os mesmos dados (cada algoritmo trabalhou sobre uma c opia do vetor original). Testamos duas vers oes do quicksort: Quick Sort 1 usa sempre o primeiro elemento do sub-vetor como piv o. Quick Sort 2 usa a mediana dos 3 primeiros elementos. O c odigo-fonte do programa est a dispon vel como perf.c na p agina do curso. A Figura 2 mostra os resultados, obtidos em um Athlon64 3200+ (2.0 GHz). Como esperado, Bubble Sort e o pior dos algoritmos quadr aticos. Na Figura 2a sequer conseguimos 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: Compara c ao da performance dos algoritmos de ordena c ao.

ver os resultados do Merge Sort e Quick Sort, devido ` a diferen ca de performance entre algoritmos quadr aticos e log-lineares. As Figuras 2b e 2c mostram Merge Sort e Quick Sort isoladamente. Note que o uso da mediana de 3 n ao teve efeito no Quick Sort para dados aleat orios. Em algumas situa c oes, com dados viciados, o uso da mediana poderia evitar comportamento quadr atico do 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 d ecimos de segundo, e e razo avel escolher um algoritmo ruim por em mais simples de implementar. A Figura 2a deve deixar claro que, para vetores grandes, qualquer algoritmo log-linear e muito melhor que qualquer algoritmo quadr atico. E a Figura 2b mostra que, embora Mergesort garanta log-linearidade, na pr atica o Quicksort e mais eciente. A Tabela abaixo mostra o n umero de linhas (excluindo linhas em branco e de coment ario) usadas na implementa c ao de cada algoritmo. Algoritmo Bubble Sort Selection Sort Insertion Sort Merge Sort Quick Sort 1 Quick Sort 2 Linhas 9 12 10 27 20 26

Vous aimerez peut-être aussi