Você está na página 1de 8

Quicksort Externo

Fabiano Cupertino Botelho 1


Ligiane Alves de Souza 2
1,2

UFMG Universidade Federal de Minas Gerais


DCC Departamento de Cincia da Computao
{fbotelho,ligiane}@dcc.ufmg.br

Resumo: Pretende-se com este artigo descrever o Quicksort Externo, um algoritmo


para ordenao externa in situs, e comparar sua implementao na linguagem C
com softwares eficientes para ordenao externa. As mtricas utilizadas na
comparao so tempo de execuo e quantidade de espao total utilizado na
ordenao. Por fim, pretende-se averiguar empiricamente a sua complexidade de
caso mdio levando em considerao o nmero de operaes de entrada e sada
efetuadas.
Palavras chaves: Ordenao externa, Quicksort Externo.

1 Introduo
Atualmente, a necessidade de ordenar grandes volumes de dados tem se tornado muito
importante para grandes corporaes, instituies governamentais, bancos e outros. Como no
possvel armazenar todos os dados na memria principal de um computador, mecanismos
eficientes de ordenao em memria secundria, tambm conhecida como ordenao externa,
devem ser utilizados.
Diferentemente dos algoritmos de ordenao interna, onde a principal operao considerada
na anlise dos algoritmos a comparao entre chaves, o principal objetivo em ordenao
externa minimizar o nmero de operaes de entrada e sada (E/S) executadas. Isto porque o
tempo para se realizar uma operao de E/S muito maior do que o tempo de uma operao da
unidade central de processamento.
A gerncia da quantidade de operaes de E/S executadas por um algoritmo de ordenao
pode ser feita de duas formas. A primeira delas quando o algoritmo de ordenao projetado
para utilizar somente a memria interna disponvel e com o objetivo de minimizar o nmero de
operaes de E/S efetuadas. Em [Leu, 00], citado que o limite inferior, considerando o nmero
de operaes de E/S, para se ordenar n registros dado por:

n
n log
b
O

K
b log
b

(I )

sendo K o nmero de registros que podem ser armazenados na


memria interna; b a quantidade de registros que podem ser
armazenados no bloco de leitura ou gravao do Sistema
Operacional (SO). Caso K

n
b

ser O

n b , o limite inferior passa a

(II ) .

Na outra abordagem de gerncia do nmero de operaes de E/S, utilizado um algoritmo


de ordenao interna tradicional, tal como Quicksort [Hoare, 62] [Ziviani, 93] ou heapsort
[Ziviani, 93], porm no levado em considerao que a memria interna seja limitada. Isto
possvel em SOs que implementam um mecanismo de memria virtual, o qual gerencia as
operaes de E/S. Nessa abordagem, para minimizar o nmero de operaes de E/S, os
algoritmos devem possuir caractersticas que diminuam a quantidade de faltas de pginas no
mecanismo de memria virtual. Sedgewick [Sedgewick, 83] cita que o Quicksort um bom
mtodo para ser utilizado nesse ambiente, pois possui uma pequena localidade de referncia.
Isto diminui o nmero de faltas de pginas em um ambiente de memria virtual. Para estudos
mais detalhados sobre o Quicksort em memria virtual pode-se consultar [Verkamo, 87].

Outro fator importante diz respeito quantidade de memria extra utilizada para a ordenao
externa. Basicamente, so utilizadas duas abordagens. A primeira a ordenao in place
[Monard, 80], tambm conhecida como ordenao in situs. Nela, a entrada ordenada de
forma que o arquivo original seja sobrescrito. O mtodo utiliza somente O(log n) unidades de
memria interna, onde n o nmero de registros a serem ordenados, sendo que no necessrio
nenhuma memria externa alm da que utilizada pelo arquivo original. Na outra abordagem,
no h restrio quanto ao uso extra de memria interna ou externa.
Na seo 2, apresentado o Quicksort Externo, um algoritmo para ordenao externa
proposto por Monard [Monard, 80] que se enquadra na abordagem de ordenao in situs e
utiliza uma tcnica semelhante ao Quicksort tradicional [Hoare, 62] [Ziviani, 93]. Na seo 3, o
Quicksort Externo comparado com softwares que realizam eficientemente a ordenao
externa. Os softwares escolhidos foram o Nitrosort [Nitrosort, 03] e o Sort. O primeiro foi
escolhido por ser um produto comercial muito eficiente e o segundo por ser muito popular, j
que um aplicativo presente em vrios SOs. As principais mtricas utilizadas na avaliao
foram a quantidade de espao extra utilizado por cada um deles e a eficincia em termos de
tempo de execuo. Apesar de no ser um dos objetivos primrios, foram realizados testes com
o Quicksort tradicional fazendo uso do ambiente de memria virtual, e os resultados foram
comparados com os do Quicksort Externo. Enfim, na seo 4 o artigo concludo e alguns
estudos so propostos.

2 Quicksort Externo
O Quicksort Externo um algoritmo que utiliza o mtodo de diviso e conquista para
ordenar in situs um arquivo A = {R1,K, Rn } de n registros armazenados consecutivamente em

memria secundria de acesso randmico. Considerando que Ri, onde 1 i n , o registro que
se encontra na i-sima posio de A, o primeiro passo do algoritmo particionar A da seguinte
forma: {R1 ,K, Ri } Ri+1 Ri+ 2 K R j 2 R j 1 R j ,K, Rn , utilizando para isto um

buffer na memria interna de tamanho K = j i + 1, com K 3 . Logo aps, o algoritmo

chamado recursivamente em cada um dos subarquivos A1 = {R1,K, Ri } e A2 = Rj ,K, Rn , sendo

que primeiramente ordenado o subarquivo de menor tamanho. Esta condio necessria para
que, na mdia, o nmero de subarquivos com o processamento adiado no ultrapasse log n.
Subarquivos vazios ou com um nico registro so ignorados. Caso o arquivo de entrada A
possua no mximo K registros ele ordenado em um nico passo, ou seja, cada registro do
arquivo lido e escrito uma nica vez. Um pseudocdigo, obtido de Monard [Monard, 80], para
o Quicksort Externo exibido abaixo:
procedure quicksort_externo(esq, dir);
{esq e dir so, respectivamente, os endereos do primeiro e do ltimo registro de A}
i, j: Integer;
if dir - esq >= 1 then
particao(esq, dir,i, j);
if i - esq < dir - j then {Ordena primeiro o menor subarquivo}
quicksort_externo(esq, i);
quicksort_externo(j, dir);
else
quicksort_externo(j, dir);
quicksort_externo(esq, i);
end if
end if
end procedure

Cdigo 1: procedimento do Quicksort Externo.

Uma questo importante como so determinados os pontos i e j de partio do arquivo. Os


valores das chaves dos registros Ri e Rj so denominados, respectivamente, limite inferior Linf e
superior Lsup. O objetivo do procedimento particao chamado no Cdigo 1 copiar todos os
registros menores ou iguais a Ri para A1 e todos os maiores ou iguais a Rj para A2. Inicialmente,
Linf = e Lsup = + .
A leitura de A controlada por dois apontadores RL (read lower) e RU (read upper), que
apontam, no incio, para os extremos esquerdo e direito de A, respectivamente. Da mesma
forma, a escrita em A controlada por WL (write lower) e WU (write upper). Os registros do
arquivo A so lidos pelo procedimento particao, alternadamente, dos extremos de A at que
K 1 registros tenham sido lidos e armazenados no buffer interno. A cada leitura no extremo
esquerdo, RL incrementado de um e a cada leitura no extremo direito, RU decrementado de
um. O mesmo ocorre com WL e WU quando escritas so realizadas no extremo que controlado
por cada um destes apontadores. Para garantir que os apontadores de escrita estejam, pelo
menos, um passo atrs dos apontadores de leitura, a ordem alternada de leitura interrompida se
RL = WL ou RU = WU. Somente uma dessas condies verdadeira em um determinado instante,
pois K 3 . Isto faz com que nenhuma informao seja destruda durante a ordenao do
arquivo.
Ao ler o K-simo registro, sua chave C comparada com Lsup. Caso seja maior, o valor de
WU atribudo a j e o registro escrito em A2. Caso contrrio, sua chave comparada com Linf;
sendo menor, o valor de WL atribudo a i e o registro escrito em A1. Se Linf C Lsup , o
registro inserido no buffer. Neste momento, o buffer se encontra cheio e uma deciso
deve ser tomada para remover um elemento do mesmo. Esta deciso tomada levando em
considerao o tamanho atual de A1 e A2 que so, respectivamente, T1 = WL esq e

T2 = dir WU . Caso T1 < T2 , o registro R de menor chave CR extrado do buffer e escrito


na posio apontada por WL em A1. Neste momento, o valor de Linf atualizado com o valor de
CR. Caso contrrio, o registro R de maior chave CR extrado do buffer e escrito na posio
apontada por WU em A2. Neste momento, o valor de Lsup atualizado com o valor de CR. O
objetivo de se tomar tal deciso sempre escrever o registro retirado do buffer no arquivo de
menor tamanho. Desta forma, o arquivo original A dividido to uniformemente quanto
possvel. Assim, a rvore gerada pelas chamadas recursivas de quicksort_externo ser mais
balanceada, o que, como provado em Monard [Monard, 80], um dos critrios para minimizar a
quantidade de operaes de E/S efetuadas pelo algoritmo. O outro critrio seria aumentar o
tamanho do buffer interno.
O processo de partio continua at que RL e RU se cruzem, ou seja, RU < RL. Neste instante,
existiro K 1 registros no buffer interno, os quais devem ser copiados j ordenados para A.
Para isto, enquanto existir elementos no buffer, o menor deles extrado e escrito na posio
apontada por WL em A.
Um pseudocdigo para o procedimento particao, gerado a partir do apresentado por Monard
[Monard, 80], exibido no Cdigo 2. Nele, o procedimento readup l em last_read o registro
apontado por RU, decrementa RU de um e atribui false a up_reading. Da mesma forma,
readlow l em last_read o registro apontado por RL, incrementa RL de um e atribui true a
up_reading. J o procedimento writeup(r) escreve o registro r na posio apontada por WU e
decrementa WU de um. Semelhantemente, writelow(r) escreve o registro r na posio apontada
por WL e incrementa WL de um. Os procedimentos extractup e extractlow removem e
retornam, respectivamente, o maior e o menor elemento do buffer interno. Alm disso, ambos
decrementam no_buffer de um.
procedure particao (esq, dir, i, j)
RU := WU := dir;

{Apontadores superiores de E/S}

RL := WL := esq;

{Apontadores inferiores de E/S}

no_buffer := 0;

{Nmero de registros no buffer}

Linf :=

{Limite inferior de partio}

Lsup := + ;

{Limite superior de partio}

up_reading;

{flag que faz com que a leitura seja alternada}

last_read;

{contm o ltimo registro lido}

i := esq 1;

{inicia com o subarquivo esquerdo vazio}

j := dir + 1;

{inicia com o subarquivo direito vazio}

while RU RL do
if no_buffer < K - 1 then
if up_reading then readup() else readlow(); end if
inserir_buffer(); {insere last_read no buffer e incrementa no_buffer}
else

if RU = WU then readup();
else

if RL = WL then readlow();
else if up_reading then readup() else readlow(); end if end if

end if
if last_read.chave > Lsup then
j := WU;
writeup(last_read);
else

if last_read.chave < Linf then


i := WL;
writelow(last_read);
else

inserir_buffer();
if WL esq < dir - WU then
r := extractlow(); writelow(r);
else

r := extractup(); writeup(r); end if

end if
end if
end if
end do
while WL WU do r := extractlow(); writelow(r); end do
end procedure

Cdigo 2: procedimento que realiza a partio do arquivo a ser ordenado.


Como os controladores de disco lem e escrevem os dados em blocos, Monard [Monard, 80]
tambm props a utilizao de buffers para leitura e escrita de registros, com o objetivo de
diminuir o nmero de operaes de E/S. Isto pode ser feito utilizando dois buffers de entrada
e dois de sada. Desta forma, cada registro pode ser lido do buffer de entrada do extremo
esquerdo ou direito do arquivo e escrito no buffer de sada do extremo esquerdo ou direito.
Quando um buffer de leitura de um dos extremos estiver vazio e uma leitura for solicitada ao
mesmo, o buffer reabastecido pela leitura de um novo bloco de dados daquele extremo no
arquivo original. Uma analogia pode ser feita em relao aos buffers de sada, pois quando
um destes estiver cheio e uma escrita for solicitada, o buffer deve ser descarregado no
respectivo extremo do arquivo original. Isto deve ser feito antes do novo registro ser
armazenado no buffer.
O Quicksort Externo, tal como descrito, foi implementado com o objetivo de verificar a sua
eficincia de tempo e espao em relao aos programas Nitrosort [Nitrosort, 03] e Sort. Monard
[Monard, 80] no especificou a forma de gerncia do buffer interno de tamanho K. Apenas
sugeriu algumas estruturas, como arranjo ordenado, heaps paralelos e outros. Neste trabalho, a
estrutura escolhida para o buffer foi uma lista duplamente encadeada implementada em vetor

e mantida ordenada, de forma que o maior e o menor registros possam ser removidos do
buffer com custo O(1). Esta abordagem impe a sobrecarga de manter a lista ordenada.
Porm, testes executados indicaram que tal sobrecarga no compromete o desempenho do
Quicksort Externo, desde que o buffer no seja muito grande.
Aps termos detalhado todas as caractersticas do Quicksort Externo, exibiremos agora a sua
complexidade, a qual foi demonstrada em Monard [Monard, 80]. A complexidade de melhor

n
b

caso do algoritmo O ( III ) , que ocorre, por exemplo, quando o arquivo de entrada j se

n2
encontra ordenado. A complexidade de pior caso O ( IV ) e ocorre quando um dos
K
arquivos retornados pela rotina de partio tem o maior tamanho possvel e o outro vazio, ou
seja, a rvore gerada pelas chamadas recursivas totalmente degenerada. Monard [Monard, 80]
provou que, medida que n cresce, tanto a probabilidade de ocorrncia do pior caso quanto a do
melhor tendem a zero, sendo que a probabilidade do melhor caso sempre maior do que a do
pior. Enfim, em uma demonstrao exaustiva, Monard [Monard, 80] provou que a

complexidade do caso mdio O log (V ) . Comparando esta complexidade com a


K
b
equao (I), apresentada na seo 1, percebe-se que na mdia o Quicksort Externo executa um
nmero pouco maior de operaes de E/S do que o exigido no limite inferior do problema de
ordenao externa.

3 Estudos empricos
Os estudos empricos foram realizados no ambiente Cygwin [Cygwin, 03] em uma mquina
equipada com um processador AMD Atlon XP 2GHz, 512 MB de memria RAM e com o
sistema operacional Windows XP. Os arquivos utilizados nos testes continham registros de
inteiros de 4 bytes gerados aleatoriamente. Os tamanhos destes arquivos variaram de 1 MB a
1536 MB, como pode ser visto nas Tabelas 1 e 2.
Para possibilitar uma comparao justa, procurou-se por softwares eficientes que realizassem
ordenao in situs, tal como o Quicksort Externo. No entanto, como no se teve acesso a
nenhum software com tais caractersticas, foi utilizado nos testes um programa que no ordena
arquivos de forma in situs, mas que comprovadamente eficiente. O programa escolhido foi o
Nitrosort, desenvolvido pela Cole-Research [Nitrosort, 03]. O Nitrosort necessita de, no
mnimo, o dobro do espao do arquivo original na memria externa e, portanto, no pode ser
classificado como um software de ordenao in situs. Por ser um software proprietrio, no
tivemos acesso ao mtodo de ordenao externa utilizado pelo Nitrosort. No entanto, ao entrar
em contato com os desenvolvedores do mesmo, estes nos informaram que o mtodo baseado
na ordenao interna e intercalao externa de runs. Um run um segmento do arquivo
original que ordenado na memria interna. Existem vrios mtodos na literatura baseados
neste paradigma, tais como os citados em Islam [Islam, 03] e Leu [Leu, 00], sendo que o ltimo
apresenta um algoritmo timo.
Em seguida, tratou-se de delimitar a quantidade de memria interna que seria utilizada pelos
algoritmos avaliados. Foram executados testes preliminares, nos quais o Quicksort Externo
apresentou um bom desempenho para buffers capazes de armazenar 100 registros. Como
foram utilizados cinco buffers, a memria total consumida pelo Quicksort Externo foi de 2000
bytes. O Nitrosort permite variar a quantidade de memria interna utilizada, sendo que o valor
mnimo suportado de 1 MB. Para fazer uma comparao justa, procurou-se encontrar a menor
quantidade de memria com a qual o Nitrosort apresentasse um bom desempenho. Esta
quantidade foi especificada em 3 MB, j que para valores inferiores, o Nitrosort demonstrou ser
muito menos eficiente que o Quicksort Externo. O valor ideal, sugerido pelos desenvolvedores
do software, de 21 MB. Neste caso, o Nitrosort chegou a ser duas vezes mais rpido que o
Quicksort Externo. Porm, medida que o arquivo cresce, esta proporo diminui rapidamente

e, aps um determinado limite, o Quicksort Externo mais rpido. Esta caracterstica tambm
pode ser observada nos dados obtidos com 3 MB, veja Tabela 1 e Grfico 1.
Os dados coletados nos testes foram coerentes com a complexidade de caso mdio para o
Quicksort Externo exibida na seo 2. Para averiguar isto, pode-se utilizar a seguinte equao
para estimar o tempo de execuo a partir da complexidade de caso mdio:

Texe =

n n
log t (VI ) , onde t uma constante que foi obtida a partir da mdia de subb
K

constantes calculadas pela aplicao da equao (VI), utilizando os tempos de execuo da


coluna Q. E. (Quicksort Externo) da Tabela 1. O ideal seria que o valor de t fosse dado pela
equao t = Cte t1 op E / S , onde Cte seria uma constante assinttica e t1 op E/S o tempo de
execuo de uma operao de E/S na arquitetura onde os testes foram efetuados.
Arquivos
(MB)
1
2
4
8
16
32
64
128
256
512
1024
1536

Estimado

Q. E.

1.07
2.31
4.98
10.68
22.79
48.45
102.64
216.76
456.50
958.94
2009.77
3095.29

1.19
2.23
4.92
11.14
20.05
49.42
85.73
184.61
412.48
1029.41
2139.80
3890.72

Nitrosor
t
1.44
1.56
2.33
3.61
7.19
13.59
26.92
56.33
123.30
560.45
2154.42
4650.08

Grfico 1: Grfico dos dados da Tabela 1

Tabela 1: Tempos de execuo em segundos.


Como mencionado na seo 1, o Quicksort Externo foi comparado com o software Sort.
Assim como o Nitrosort, Sort no efetua ordenao in situs, pois tambm necessita de
memria externa extra para ordenar o arquivo de entrada. Uma peculiaridade do Sort que ele
somente ordena linhas de um arquivo texto. Por isso, os testes com o Sort foram executados
separadamente e os dados de entrada, tanto do Quicksort Externo quanto do Sort, tiveram que
ser adaptados de forma que os arquivos possussem o mesmo tamanho e o mesmo nmero de
registros. Um registro do arquivo de entrada para o Quicksort Externo corresponde a uma linha
do arquivo de entrada para o Sort. Os dados coletados nos testes so exibidos na Tabela 2 e
ilustrados no Grfico 2.
Arquivo (MB)
1
2
4
8
16
32
64
128
256
512
1024

Q. E.
1.17
1.84
4.98
10.00
19.58
41.45
98.83
161.38
425.33
1047.64
2077.05

Sort
0.38
1.08
2.19
4.69
9.89
20.50
42.11
84.41
304.38
980.34
2137.23

Grfico 2: Grfico dos dados da Tabela 2

Tabela 2: Tempos de execuo em segundos.

Avaliando os resultados apresentados em termos das mtricas propostas na seo 1, percebese que a eficincia de tempo do Quicksort Externo est prxima tanto do Nitrosort quanto do
Sort. Sendo que, com o aumento do tamanho da entrada, o Quicksort Externo tende a ser mais
eficiente. Em contrapartida, em termos de espao de memria interna utilizada, o Quicksort
Externo cerca de 1500 vezes mais eficiente que o Nitrosort. Este valor foi obtido pela razo da
memria interna delimitada para o Nitrosort (3 MB) e a delimitada para o Quicksort Externo
(2000 B). No foi possvel fazer a mesma anlise para o Sort, pois no foi encontrado o
tamanho da memria interna que este utiliza como buffer para operaes de E/S.
Enfim, foram executados dois testes comparando o Quicksort tradicional em ambiente de
memria virtual e o Quicksort Externo. Novamente, o Quicksort Externo se mostrou mais
eficiente com o crescimento do tamanho da entrada, veja Tabela 3.
Tamanho do Arquivo (MB)
1024
1536

Quicksort Externo
2139.80
3890.72

Quicksort em memria virtual


2080.59
5191.81

Tabela 3: Tempos de execuo em segundos.

4 Concluses
Diante do que foi apresentado, pode-se concluir que o Quicksort Externo um algoritmo
muito adequado para ambientes com poucos recursos. Isto porque ele faz ordenao in situs
de forma eficiente, mesmo com pouca memria interna disponvel. Alm disso, seu
comportamento, no que diz respeito a tempo de execuo, est prximo do comportamento
verificado para os softwares utilizados nas comparaes.
Tal comportamento era esperado, pois o Quicksort Externo, apesar de possuir uma
complexidade de pior caso quadrtica, possui uma complexidade de caso mdio prxima do
nmero mnimo de operaes de E/S necessrias para ordenar externamente um arquivo.
Como proposta para futuros trabalhos, pode-se sugerir, primeiramente, um estudo do
impacto no tempo de execuo do Quicksort Externo de diferentes estruturas de dados para
gerenciamento do buffer interno de tamanho K. Alm disso, este mesmo estudo poderia
determinar o tamanho ideal do buffer interno e dos buffers de entrada e sada para cada uma
das estruturas. Outro estudo poderia ser feito no sentido de tentar melhorar o Quicksort Externo,
visando diminuio do nmero de operaes de E/S realizadas. importante mencionar que o
problema de ordenao externa tem sido muito pesquisado e novas tcnicas e algoritmos foram
propostos aps a publicao do Quicksort Externo. Assim, um estudo poderia buscar a
conciliao das vantagens dessas novas tcnicas com as apresentadas para o Quicksort Externo
em um novo algoritmo.

Referncias Bibliogrficas
[Cygwin, 03]

Cygwin. A Linux-like environment for Windows. Disponvel em


<http://www.cygwin.com>, acessado em agosto de 2003.

[Hoare, 62]

Hoare, C.A.R. Quicksort. The Computer Journal 5, p. 1015, 1962.

[Islam, 03]

Islam, R., Adnan, N., Islam, N., Hossen, S. A new external sorting
algorithm with no additional disk space. Information Processing
Letters 86, p. 229233, 2003.

[Leu, 00]

Leu, F.C., Tsai, Y.T., Yang, C.Y. An efficient external sorting


algorithm. Information Processing Letters 75, p. 159163, 2000.

[Monard, 80]

Monard, M.C. Projeto e Anlise de Algoritmos de Classificao


Externa Baseados na Extratgia de Quicksort. D. Tese, Pontifcia
Univ. Catlica, Rio de Janeiro, 1980.

[Nitrosort, 03]

Nitrosort. Software de ordenao externa desenvolvido pela ColeResearch. Disponvel em <http://www.cole-research.com>, acessado em
agosto de 2003.

[Sedgewick, 83]

Sedgewick, R. Algorithms. Addison-Wesley, Reading, Mass., 1983.

[Verkamo, 87]

Verkamo, A.I. Performance of Quicksort Adapted for Virtual


Memory Use. The Computer Journal, v. 30, n. 4, 1987.

[Ziviani, 93]

Ziviani, N. Projeto de Algoritmos com Implementaes em Pascal e


C. ed. Pioneira Thomson Learning, 1993.