ISSN 2317-3297
Quicksort e Quicksort Aleatorizado: Um estudo comparativo
Fábio Henrique de Farias,
Fabiano Barbosa Mendes da Silva,
José Belmiro Neto
Universidade Federal Rural de Pernambuco - UFRPE
Unidade Acadêmica de Garanhuns
55296-901, Garanhuns, PE
E-mail: [email protected].
Palavras-chave: Algoritmo, Ordenaçãoo, Particionamento, Vetor aleatório, Complexidade.
Resumo: Neste estudo, evidenciamos um método para a ordenação de elementos que visa um
menor custo computacional: o quicksort aleatorizado. Este método utiliza amostragem aleatória
durante a realização de uma sub-rotina (particionamento), obtendo um bom tempo de execução
no caso médio (em geral, bem melhor que o quicksort, com o qual o comparamos) e nenhuma
entrada especı́fica induz o seu comportamento ao pior caso. Apresentamos ainda resultados obtidos de testes preliminares com os dois métodos, tabulando segundo alguns critérios selecionados,
tais como o tempo de execução e a quantidade de trocas.
1
Introdução
O algoritmo quicksort (QS) é um algoritmo de ordenação cujo tempo de execução no pior caso é
da ordem de Θ(n2 ) sobre um arranjo de entrada de n números. Apesar desse tempo de execução
ser lento no pior caso, este algoritmo é frequentemente usado como uma boa opção prática
para ordenação, devido a sua grande eficiência na média, cujo tempo de execução esperado é
Θ(nlogn) e os fatores ocultos nesta notação são muito pequenos. Apresenta ainda a vantagem
de ordenação local e funciona bem até em ambientes de memória virtual. O quicksort baseia-se
no paradigma da divisão e conquista. Esse processo de dividir e conquistar, segundo Cormen
[1], é realizado em três passos: dividir, conquistar e combinar.
2
O Quicksort
O algoritmo quicksort recebe um vetor A[p...r] e o rearranja em ordem crescente. Seu desempenho depende do fato do particionamento ser balanceado ou não balanceado e isso depende de
quais elementos são usados para particionar. Se o particionamento é balanceado, o algoritmo
é executado assintoticamente tão rápido quanto a ordenação por intercalação. Porém, se ele é
não balanceado, o algoritmo pode ser executado assintoticamente tão lento quanto a ordenação
por inserção.
O Subproblema da Separação: A parte principal do algoritmo quicksort objetiva a resolução do seguinte problema: rearranjar A[p...r] de modo que todos os elementos pequenos
fiquem na parte esquerda do vetor e todos os elementos grandes fiquem na parte direita. Este
é o subproblema da separação (particionamento), cujo ponto de partida para determinar sua
88
ISSN 2317-3297
solução é a escolha de um ”pivô”, digamos x. Os elementos do vetor que forem maiores que x
serão considerados grandes e os demais serão considerados pequenos. É preciso escolher x de tal
modo que cada uma das duas partes do vetor rearranjado seja estritamente menor que o vetor
todo [2].
Desempenho: Realizamos os estudos de desempenho para o pior caso, para o melhor caso
e para o caso médio. Para o primeiro deles, após alguns cálculos, concluı́mos que seu tempo de
execução não é melhor do que o da ordenação por inserção, que é executada no tempo O(n).
Na divisão mais uniforme possı́vel, o algoritmo produz dois subproblemas, cada um de tamanho
não maior que n = 2, pois um tem tamanho ⌊n/2⌋ e o outro tem tamanho ⌈n/2⌉ − 1. Nesse caso,
o Quicksort (QS) é executado com muito mais rapidez. A recorrência pelo tempo de execução
é então T (n) ≤ 2T (n/2) + Θ(n), que, segundo o Teorema Mestre ([1], p.59), tem a solução
T (n) = O(nlgn). O tempo de execução do caso médio de QS é muito mais próximo do melhor
caso que do pior caso. Isso decorre do fato de que o equilı́brio do particionamento se reflete
na recorrência que descreve o tempo de execução. Desse modo, com uma divisão realizada em
qualquer proporção constante, o quicksort tem custo total de O(nlgn).
3
O Quicksort Aleatorizado
O quicksort aleatorizado (QSA) é obtido a partir do QS, utilizando-se uma técnica denominada amostragem aleatória, que consiste em, ao invés de sempre usar A[r] como pivô, utiliza
um elemento escolhido ao acaso a partir do subarranjo A[p...r]. Essa modificação assegura que
o elemento pivô x = A[r] tem a mesma probabilidade de ser qualquer um dos r − p + 1 elementos do subarranjo. Como o elemento pivô é escolhido ao acaso, espera-se que a divisão do
arranjo de entrada seja razoavelmente bem equilibrada na média. Os algoritmos utilizados são
RANDOMIZED-PARTITION e RANDOMIZED-QUICKSORT (ver [1]).
Desempenho do Algoritmo de Separação Aleatorizado: Segundo Cormen ([1], pp.125126), o tempo de execução do caso médio de RANDOMIZED-QUICKSORT é O(nlgn), pois, se
em cada nı́vel de recursão a divisão induzida por RANDOMIZED-PARTITION colocar qualquer
fração constante dos elementos em um lado da partição, então a árvore de recursão terá a
profundidade Θ e o trabalho O(n) será executado em cada nı́vel. Ainda que sejam adicionados
novos nı́veis com a divisão mais desequilibrada possı́vel entre esses nı́veis, o tempo total de
execução continuará a ser O(nlgn). Para realizar uma análise precisa sobre o tempo de execução
de RANDOMIZED-QUICKSORT, deve-se compreender o procedimento de particionamento e
como consequência derivar um limite O(nlgn) sobre o tempo esperado. Esse limite superior,
combinado com o limite do melhor caso Θ(nlgn) resulta em um tempo de execução esperado [4]
de Θ(nlgn).
Analisamos o pseudocódigo e em seguida o implementamos, a partir de alguns exemplos, em
linguagem JAVA. A execução dos testes durou cerca de 4 horas, produzindo dados, que foram
analisados e dispostos de forma simplificada. Para tal, usamos os métodos estáticos não instanciados a objetos quaisquer, para eliminar operações. A ferramenta utilizada foi Eclipse JAVA
EE IDE for Web Developers. Version: Helios Service Release 2, disponı́vel em 12 computadores
pessoais com a seguinte configuração: Processador Intel Core 2 Quad Q8200 de 2.33GHz com
memória de 2 GB com sistema operacional Windows Vista Business 32-bits. Foram criados três
vetores, um para armazenar o vetor gerado aleatoriamente, outro para armazenar uma cópia
do vetor aleatório, que foi utilizado para efetuar a ordenação através do QS e por último um
vetor, que também foi uma cópia daquele, para efetuar a ordenação pelo QSA. O segundo vetor
foi ordenado uma vez, e o terceiro foi ordenado n vezes, isto é, após cada ordenação foi feita
uma cópia do vetor original no terceiro, para que ele fosse ordenado novamente. Por fim, foram criados três grupos de trabalho. O primeiro (G1) foi composto por 24 vetores de tamanho
100.000, em que cada um deles foi ordenado no QS uma vez e ordenado no QSA 10.000 vezes. O
89
ISSN 2317-3297
segundo (G2), de forma análoga à primeira, tinha 1040 vetores de tamanho 10.000, ordenados
no QSA 2.000 vezes. Por último, no grupo G3, de modo análogo, foram criados 8.000 vetores
de tamanho 1.000 e ordenados em QSA 500 vezes.
Resultados e Discussão: Em G1, houve 240.000 ordenações no QSA, no qual verificamos
que, em geral, 3,82 % das ordenações tiveram um resultado melhor que na ordenação pelo QS.
Nesse grupo, todos os 24 vetores utilizados obtiveram um ou mais resultados positivos a favor
da ordenação aleatória. Observamos que no QSA ouve uma diminuição de até 3.927 trocas,
mas que também ocorreu um acréscimo de até 8.316 trocas, em determinados casos. Para o
G2, os 1.040 vetores foram ordenados 2.080.000 vezes no QSA. Genericamente, 8,43 % destas
ordenações deixaram o QSA em vantagem. As maiores discrepâncias foram 1.466 trocas a favor
do QSA e em seguida o contrário: 1.526 a favor do QS (o QSA teve mais passos). Observamos
ainda que 192 vetores não conseguiram ser ordenados mais eficientemente no QSA. No grupo G3,
foram criados 8.000 vetores e ordenados 4.000.000 de vezes. Em 20,09 % das ordenações o QSA
foi novamente mais eficiente, pois conseguiu até 207 passos a menos que o QS. Os resultados
obtidos através desses testes preliminares, reforçam a ideia de que a utilização do randomizedquicksort é uma alternativa bastante interessante, pois representa uma evolução, a menos de
pequenas modificações do quicksort, posto que, em média, estabelece um tempo de execução
muito menor do que o algoritmo original. Desse modo, além do aprofundamento dos estudos
de complexidade desse algoritmo, este trabalho desperta o interesse em estabelecer comparações
entre outras técnicas que utilizem uma componente aleatória para a resolução de problemas de
ordenação, o que deve possibilitar a criação de algoritmos mais eficientes para solucionar essa
categoria de problemas.
Tabela 1: Resumo do estudo comparativo entre QS e QSA
Grupos
G1
G2
G2
Tamanho do vetor
100.000
10.000
1.000
Quantidade de vetores
24
1.040
8.000
Tentativas QSA por vetor
10.000
2.000
500
Total de tentativas
240.000 2.080.000 4.000.000
Eficiência global QSA
3.82 %
8.43 %
20.09 %
Ineficiência QSA (Vetores)
0
192
129
Vantagem QSA (Passos)
3.927
1.466
207
Desvantagem QSA (Passos)
8.316
1.526
212
Referências
[1] T. H.Cormen, et al, Algoritmos: ”Teoria e Prática”. Tradução da 2a edição do ”Introduction
to Algorithms”, Rio de Janeiro: Elsevier, 2008.
[2] P. Feofiloff, ”Análise do Algoritmo Quicksort”. Notas de aula. Disponı́vel em:
http://www.ime.usp.br/pf/analisedealgoritmos. Acesso em 01 de Nov. 2011.
[3] V. Ramachandran, ”Randomized Quicksort. Lecture 6”. University of Texas at Austin.
Disponı́vel em: http://docs.google.com/ userweb.cs.utexas.edu/lr/s07.357/notes/lec6.pdf+
quicksort +randomized+running+time. Acesso em: 01 nov. 2011.
[4] D.Gildea, ”Design and Analysis of Efficient Algorithms. Lecture 7”. University of Rochester.
Disponı́vel em: http://www.cs. rochester.edu/gildea/csc282. Acesso em 01 nov. 2011.
90
Download

P-ICComputação CientíficaQuicksort e Quicksort Aleatorizado