Quick Sort
-
Upload
flavia-gomes -
Category
Documents
-
view
4 -
download
0
description
Transcript of Quick Sort
-
Quicksort
O problema da ordenao consiste em rearranjar um vetor v[0..n-1] em ordem
crescente, ou seja, permutar os elementos do vetor de modo que tenhamos v[0] v[1]
. . . v[n-1].
O algoritmo Quicksort, inventado por C.A.R. Hoare em 1962, resolve o problema. Em
algumas raras instncias, o Quicksort pode ser to lento quanto os algoritmos
elementares; mas em geral muito rpido. Mais precisamente, o algoritmo consome
tempo proporcional a n log n em mdia e proporcional a n2 no pior caso.
Usaremos duas abreviaturas ao discutir o algoritmo. A expresso v[i..k] x ser
usada como abreviatura de v[j] x para todo j no conjunto de ndices i..k.
Analogamente, a expresso v[i..k] v[p..r] ser interpretada como v[j] v[q]
para todo j no conjunto i..k e todo q no conjunto p..r.
O problema da separao
O ncleo do algoritmo Quicksort o seguinte problema da separao (= partition
subproblem), que formularemos de maneira propositalmente vaga:
rearranjar um vetor v[p..r] de modo que todos os elementos pequenos fiquem na
parte esquerda do vetor e todos os elementos grandes fiquem na parte direita.
O ponto de partida para a soluo deste problema a escolha de um piv, digamos c. Os
elementos do vetor que forem maiores que c sero considerados grandes e os demais
sero considerados pequenos. importante escolher c de tal modo que as duas partes
do vetor rearranjado sejam estritamente menores que o vetor todo. A dificuldade est
em resolver o problema da separao de maneira rpida sem usar muito espao de
trabalho.
O problema da separao admite muitas formulaes concretas. Eis uma primeira:
rearranjar v[p..r] de modo que tenhamos
v[p..j] v[j+1..r]
para algum j em p..r-1. (Nesta formulao, o piv no explcito.) Eis outra
formulao: rearranjar v[p..r] de modo que
v[p..j-1] v[j] < v[j+1..r]
para algum j em p..r. Esta pgina usa a segunda formulao; outras formulaes so
mencionadas nos exerccios.
Exerccios 1
-
1. Positivos e negativos. Escreva uma funo que rearranje um vetor v[p..r] de inteiros de modo que tenhamos v[p..j-1] 0 e v[j..r] > 0 para algum j em p..r+1. Faz sentido exigir que j esteja em p..r? Procure fazer uma funo rpida que no use vetor auxiliar. Repita o exerccio depois de trocar v[j..r] > 0 por v[j..r] 0. Faz sentido exigir que v[j] seja 0?
2. Um vetor v[p..r] est arrumado se existe j em p..r tal que v[p..j-1] v[j] < v[j+1..r] . Escreva um algoritmo que decida se v[p..r] est arrumado. Em caso afirmativo, o seu algoritmo deve devolver o valor de j.
3. Critique a seguinte verso do algoritmo da separao: 4. int sep( int v[], int p, int r) { 5. int w[1000], i = p, j = r, c = v[p], k; 6. for (k = p+1; k
-
}
A funo rearranja o vetor v[p..r] e devolve um elemento j do conjunto p..r tal que
v[p..j-1] v[j] < v[j+1..r] .
Gostaramos que j ficasse a meio caminho entre p e r, mas devemos estar preparados
para aceitar os casos extremos j == p e j == r .
p j r
c c c c c > c > c > c > c > c
Algumas perguntas que chamam a ateno para detalhes importantes: Que acontece se
executarmos a funo com p igual a r? Que acontece se eliminarmos i = p na linha 4? Que acontece se escrevermos i > j na
linha 5? Que acontece se trocarmos j por i nas linhas 9 e 10?
Anlise do algoritmo da separao
Eu prefiro escrever a funo separa de maneira um pouco diferente para facilitar a
anlise de sua correo:
// Recebe vetor v[p..r] com p < r. Rearranja os
// elementos do vetor e devolve j em p..r tal que
// v[p..j-1]
-
Na penltima passagem peo ponto A, teremos
p i=j r
c c c c c ? > c > c > c > c
Na ltima passagem pelo ponto A valem as seguintes relaes:
i == j+1 p j r v[p+1..j] c e v[j+1..r] > c.
Portanto, v[p..j-1] v[j] < v[j+1..r] na fim da execuo da funo, como
prometido.
Desempenho do algoritmo da separao
Qual o desempenho da funo separa? Quanto tempo a funo consome? O consumo
de tempo proporcional ao nmero de comparaes entre elementos do vetor. No
difcil perceber que esse nmero proporcional ao nmero r - p + 1 de elementos
do vetor.
Exerccios 2
1. Qual o resultado da funo separa quando os elementos de v[p..r] so todos iguais? E quando v[p..r] crescente? E quando v[p..r] decrescente? E quando cada elemento de v[p..r] tem um de dois valores possveis?
2. A funo separa produz um rearranjo estvel do vetor, ou seja, preserva a ordem relativa de elementos de mesmo valor?
3. Analise e discuta a seguinte verso da funo separa. Ela equivalente do livro de Cormen, Leiserson, Rivest e Stein.
4. int separa_CLRS( int v[], int p, int r) { 5. int c = v[r], i = p, j, t; 6. for (j = p; j < r; ++j) { 7. if (v[j]
-
25. v[p] = v[j], v[j] = c; 26. return j; 27. }
28. Critique a seguinte verso do algoritmo da separao: 29. int separa( int v[], int p, int r) { 30. int c = v[p], i = p+1, j = r, t; 31. while (i