You are on page 1of 13

Algoritmos de Ordenao em Java

INICIAR

ASSINE MVP

Buscar

comentrios

favorito (3)

marcar como lido

para impresso

anotar

Algoritmos de Ordenao em Java


Veja neste artigo como funcionam os algoritmos de ordenao InsertionSort,
SelectionSort e QuickSort.

Gostei
(3)

(0)

Neste
artigo veremos como aplicar algoritmos de ordenao em Java, dada a sua devida
necessidade em ocasies
especficas. Existem diversas aplicabilidades para a
ordernao de dados, no s em Java, mas no mundo computacional
como um todo.

A
ideia de conhecer diversos algoritmos para ordenar dados saber qual utilizar
para conseguir um melhor desempenho ou
uma melhor legibilidade de cdigo,
dependendo da necessidade. No precisamos usar, por exemplo, um algoritmo

supercomplexo para ordenar 10 valores em um vetor, certo? Seria desperdcio


de tempo desenvolver um algoritmo to
complexo para resolver um problema to
simples.

Para
analisar um algoritmo de ordenao voc deve conhecer a sua complexidade no
Pior Caso, Caso Mdio e o melhor
caso. Estas trs caractersticas presentes em
todos os algoritmos dizem respeito a sua velocidade dada uma situao

especfica. Atente-se a esses conceitos, pois falaremos deles posteriormente,


citando a complexidade do algoritmo atravs
de notao matemtica.

http://www.devmedia.com.br/algoritmos-de-ordenacao-em-java/32693[30/06/2015 11:33:59]

Algoritmos de Ordenao em Java

Algoritmos
de Ordenao
InsertionSort
Sua
teoria baseia-se em ordenar os valores da esquerda para a direita, deixando os
elementos lidos (a esquerda)
ordenados. Este geralmente utilizado para
ordenar um pequeno nmero de valores, onde faz-se muito eficiente. A

complexidade do cdigo :

Complexidade
Pior Caso: O(n)
Complexidade
Caso Mdio: O(n)
Complexidade
Melhor Caso: O(n)

Quando
temos um caso onde a complexidade n devemos evitar, visto que a
reduo de desempenho deste algoritmo
exponencial. Porm, no seu melhor caso
temos uma constante n que significa a inalterao da velocidade,
proporcional
quantidade de elementos.

Lembre-se que estamos trabalhando com proporcionalidade,


ento dizer que no varia no significa que um vetor de 10
elementos ser
ordenado na mesma velocidade de um vetor de um milho de elementos, mesmo no
melhor caso, porm a
proporcionalidade entre a quantidade de elementos e sua
velocidade continua constante, diferente do Pior Caso que
aumenta ao quadrado.

O
melhor caso ocorre quando todos os elementos j esto ordenados e o pior caso
exatamente o contrrio, quando todos
os elementos esto desordenados. Vejamos
um exemplo para entender melhor essa teoria na Listagem 1.

Listagem
1. Aplicando InsertionSort

public static void main(String[] args) throws IOException {


int quantidade = 10000;
int[] vetor = new int[quantidade];
for (int i = 0; i < vetor.length; i++) {
vetor[i] = (int) (Math.random()*quantidade);
}
long tempoInicial = System.currentTimeMillis();
insertionSort(vetor);
long tempoFinal = System.currentTimeMillis();
System.out.println("Executado em = " + (tempoFinal - tempoInicial) + " ms");
}
public static void insertionSort(int[] vetor) {
int j;
int key;

http://www.devmedia.com.br/algoritmos-de-ordenacao-em-java/32693[30/06/2015 11:33:59]

Algoritmos de Ordenao em Java

int i;
for (j = 1; j < vetor.length; j++)
{
key = vetor[j];
for (i = j - 1; (i >= 0) && (vetor[i] > key); i--)
{
vetor[i + 1] = vetor[i];
}
vetor[i + 1] = key;
}
}

O
primeiro passo entender o funcionamento do mtodo insertionSort(). Este ir
percorrer todo o vetor comeando do
segundo elemento e atribuindo o mesmo a uma
varivel chamada key.

O
algoritmo comea fazendo uma iterao em todos os elementos do vetor, a partir
do segundo elemento, por isso j=1 e
no j=0.

A
varivel key armazena inicialmente o primeiro valor
lido pelo lao for, que no caso ser o segundo elemento do vetor. O
segundo
lao itera sobre os valores que esto antes da varivel key:

key = vetor[j];
for (i = j - 1; (i >= 0) && (vetor[i] > key); i--)

Perceba que a iterao mostrada continuar at que o


valor de i seja maior ou igual a zero e o valor do vetor na posio i
seja
maior que o valor de key.

Suponha o seguinte vetor: 30,20,10,40. Na primeira


iterao o valor de key ser 20, j que comeamos a iterao a partir do

segundo valor. Na primeira iterao do segundo lao for o valor de i ser igual
a 0, porque o j ser igual a 1, sendo assim o
i >= 0 e o vetor[0] maior
que 20, pois vetor[0] = 30. Ao acessar o segundo lao for feita uma
atribuio.

Temos ento que vetor[0+1] = vetor[0], ou seja, o valor


20 recebe o valor 30, ficando assim: 30,30,10,40. Quando ele tentar
passar pela
segunda vez no segundo lao for no ser possvel, pois i ser -1.

Ao sair do segundo lao for o valor de vetor[i+1] recebe


o que tnhamos armazenado em key.

No caso, vetor[-1 + 1] = 20, ento temos 20, 30, 10, 40.

O mesmo prossegue at que todos os valores do vetor


sejam percorridos e estejam ordenados.

A
varivel i serve para comparar sempre o elemento atual com o elemento
anterior, pois ele faz com que seja possvel
percorrer todos os elementos
anteriores ao atual at achar algum que seja maior que o atual, fazendo com que
este seja
substitudo. Conforme a iterao for avanando os elementos a
esquerda vo ficando ordenados.

http://www.devmedia.com.br/algoritmos-de-ordenacao-em-java/32693[30/06/2015 11:33:59]

Algoritmos de Ordenao em Java

Vejamos
agora o que foi feito dentro do mtodo main(), que ser usado durante todo o
desenvolvimento deste artigo.

O
mtodo main() possui uma iterao para preencher elementos de forma randmica:

for (int i = 0; i < vetor.length; i++) {


vetor[i] = (int) (Math.random()*quantidade);
}

Aps o preenchimento destes elementos chamado o mtodo


insertionsort(), que ir ordenar os valores, sendo que antes e
depois so
gravadas variveis do System.currentTimeMillis() para saber-se qual tempo de
execuo do algoritmo em
milissegundos.

O cdigo da Listagem
1 representa o caso mdio, onde alguns valores podem j estar ordenados e
outros no, visto que
usamos o Math.random() e no saberemos qual vetor ser
construdo. Para testar o melhor caso voc deve trocar a linha
mencionada por:

for (int i = 0; i < vetor.length; i++) {


// vetor[i] = (int) (Math.random()*quantidade);
vetor[i] = i + 1;
}

Vejamos na Tabela
1 os tempos mdios: como o pior caso e o caso mdio possuem a mesma
complexidade decidimos
fazer a anlise de apenas um destes.

InsertionSort

Elementos

Caso mdio
(n)

Melhor Caso
(n)

100

0 ms

0 ms

1.000

11 ms

0 ms

10.000

220 ms

1 ms

100.000

5110 ms

6 ms

200.000

20.272 ms

8 ms

Tabela 1. Medio de Tempo para


InsertionSort

O que podemos perceber na tabela que no caso mdio


temos uma alterao exponencial, aumentando muito o tempo
conforme o aumento do
nmero de elementos. Ao analisar os tempos voc ver um aumento considervel
quando
trabalhamos com n. Por outro lado, no melhor caso o tempo
mantem-se quase constante, enquanto temos 20.272 ms para
200.000 no caso Mdio,
temos 8 ms para a mesma quantidade no melhor Caso.

http://www.devmedia.com.br/algoritmos-de-ordenacao-em-java/32693[30/06/2015 11:33:59]

Algoritmos de Ordenao em Java

BubbleSort
O BubbleSort conhecido pela sua
simplicidade e pela eficcia ao realizar ordenaes em um nmero limitado de
valores.
Seu princpio baseia-se na troca de valores entre posies
consecutivas, fazendo com que valores altos ou baixos
(dependendo da forma de
ordenao desejada) borbulhem para o final da fila, por isso este algoritmo
chamado de
BubbleSort. Sua complexidade :

Complexidade
Pior Caso: O(n)
Complexidade
Caso Mdio: O(n)
Complexidade
Melhor Caso: O(n)

Vimos que no melhor caso o seu tempo quase


inaltervel, permanecendo constante, ou seja, um caso ideal.

Vejamos a implementao do bubbleSort na Listagem 2.

Listagem 2. BubbleSort

public static void main(String[] args) throws IOException {


int quantidade = 10000;
int[] vetor = new int[quantidade];
for (int i = 0; i < vetor.length; i++) {
vetor[i] = (int) (Math.random()*quantidade);
}
long tempoInicial = System.currentTimeMillis();
bubbleSort(vetor);
long tempoFinal = System.currentTimeMillis();
System.out.println("Executado em = " + (tempoFinal - tempoInicial) + " ms");
}
private static void bubbleSort(int vetor[]){
boolean troca = true;
int aux;
while (troca) {
troca = false;
for (int i = 0; i < vetor.length - 1; i++) {
if (vetor[i] > vetor[i + 1]) {
aux = vetor[i];
vetor[i] = vetor[i + 1];
vetor[i + 1] = aux;
troca = true;
}
}
}
}

http://www.devmedia.com.br/algoritmos-de-ordenacao-em-java/32693[30/06/2015 11:33:59]

Algoritmos de Ordenao em Java

Veja que o primeiro passo criar as


variveis que nos auxiliaro na ordenao dos valores. Um lao while() criado
e
executado enquanto o valor de troca for true, e logo na primeira iterao j
configuramos essa varivel como false (voc
entender mais frente o porqu).

O lao for percorre o primeiro elemento at o


ltimo elemento -1 (ele nunca chegar a ler o ltimo elemento) verificando se o

elemento atual que est sendo lido maior que o prximo elemento que ser
lido.

Suponhamos ento o seguinte vetor: 20, 10,


30.

A primeira iterao no lao for ir capturar


o valor 20 e comparar com o prximo, que ser 10. Ento se 20 > 10, ele
entrar
na condio fazendo a substituio destes valores:

if (vetor[i] > vetor[i + 1]) {


aux = vetor[i];
vetor[i] = vetor[i + 1];
vetor[i + 1] = aux;
troca = true;
}

O valor 20, que est na posio i


armazenado na varivel aux para no perdemos sua referncia, depois o valor 10
que
est na posio i+1 armazenado no local do valor 20. Trocamos agora o
valor de i+1 pelo valor que armazenamos em
aux, que no caso 20. A varivel
troca que antes era false, agora recebe true para indicar que houve uma troca.

Na segunda iterao do lao for o valor 20


ser capturado, pois estaremos com i = 1. O valor 20 ser comparado com o
valor
de i+1 (2), que no caso o valor 30. Ento se 20 > 30 a troca ser
realizada. Como 20 no maior que 30 no
entraremos na condio e o lao for
continuar a ser executado, agora na prxima iterao, onde i = 2.

Quando i = 2 j estamos no ltimo elemento,


ento no entrar no lao for, j que
i no menor que vetor.length 1. Se

fosse possvel entrar no ltimo elemento para realizar comparaes o seguinte


erro aconteceria:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:

Isso porque no podemos realizar a operao


de comparao do ltimo elemento com um prximo elemento, j que ele no

existe.

Porque a varivel troca til? Ao passar


pela primeira vez no vetor de elementos qualquer troca que for realizada ativa
a
varivel troca como true, fazendo com que ele precise passar novamente depois
da leitura de todos os elementos. A ideia
passar quantas vezes forem
necessrias at que a varivel troca no seja mais ativada, assim saberemos que
todos os
elementos esto devidamente ordenados.

http://www.devmedia.com.br/algoritmos-de-ordenacao-em-java/32693[30/06/2015 11:33:59]

Algoritmos de Ordenao em Java

Analisando mais a fundo o algoritmo


BubbleSort voc perceber que a segunda passada geralmente ser muito mais
rpida
que a primeira, principalmente se todo o vetor j foi ordenado
corretamente, fazendo com que nenhuma vez seja
necessrio realizar trocas, assim
o mesmo entra no melhor caso, ou seja, todos os valores ordenados.

BubbleSort

Elementos

Caso mdio
(n)

Melhor Caso
(n)

100

0 ms

0 ms

1.000

15 ms

0 ms

10.000

200 ms

0 ms

100.000

20.426 ms

2 ms

200.000

81.659 ms

4 ms

Tabela
2. Medio de Tempo para BubbleSort

Analisando
a Tabela 2 podemos perceber que at
1000 elementos o BubbleSort eficiente e realiza a ordenao de forma
eficaz,
porm com valores maiores j se torna mais lento. No melhor caso quase no h
alterao para o tempo de
resposta deste algoritmo, visto que ele apenas
passar dentro do lao for sem entrar nenhuma vez na condio para
realizar a
troca de elementos.

QuickSort
Este
algoritmo usa uma tcnica conhecida por diviso e conquista, muito conhecida
por reduzir problemas complexos em
problemas menores para tentar chegar em uma
soluo. Sendo assim, o resultado do problema inicial dada como a soma
do
resultado de todos os problemas menores. Sua complexidade :

Complexidade
Pior Caso: O(n)
Complexidade
Caso Mdio: (nlogn)
Complexidade
Melhor Caso: (nlogn)

O
QuickSort sai na frente de outros algoritmos mais simples quando tratamos do
caso mdio, por trabalhar com logaritmo
(nlogn), o que torna o resultado mais
rpido do que o InsertionSort e o QuickSort.

O
algoritmo consiste nos seguintes passos:

1. Escolhe-se um elemento qualquer da lista,


que ser chamado de piv.
2. Todos os elementos antes do piv devem ser
menores que ele e todos os elementos aps o piv devem ser maiores
que ele.
Quando esse processo de separao for finalizado, ento o piv deve estar
exatamente no meio da lista.
3. De forma recursiva os elementos da
sublista menor e maiores so ordenados.

http://www.devmedia.com.br/algoritmos-de-ordenacao-em-java/32693[30/06/2015 11:33:59]

Algoritmos de Ordenao em Java

Seu
algoritmo pode ser visto na Listagem 3.

Listagem
3. QuickSort

public static void main(String[] args) throws IOException {


int quantidade = 10000;
int[] vetor = new int[quantidade];
for (int i = 0; i < vetor.length; i++) {
vetor[i] = (int) (Math.random()*quantidade);
}
long tempoInicial = System.currentTimeMillis();
quickSort(vetor,0,vetor.length-1);
long tempoFinal = System.currentTimeMillis();
System.out.println("Executado em = " + (tempoFinal - tempoInicial) + " ms");
}
private static void quickSort(int[] vetor, int inicio, int fim) {
if (inicio < fim) {
int posicaoPivo = separar(vetor, inicio, fim);
quickSort(vetor, inicio, posicaoPivo - 1);
quickSort(vetor, posicaoPivo + 1, fim);
}
}
private static int separar(int[] vetor, int inicio, int fim) {
int pivo = vetor[inicio];
int i = inicio + 1, f = fim;
while (i <= f) {
if (vetor[i] <= pivo)
i++;
else if (pivo < vetor[f])
f--;
else {
int troca = vetor[i];
vetor[i] = vetor[f];
vetor[f] = troca;
i++;
f--;
}
}
vetor[inicio] = vetor[f];
vetor[f] = pivo;
return f;
}

O
primeiro passo separar as listas, como havamos citado anteriormente. No
mtodo separar() esse processo realizado
at que seja retornado um piv, ou
seja, o elemento divisvel entre as duas listas.

http://www.devmedia.com.br/algoritmos-de-ordenacao-em-java/32693[30/06/2015 11:33:59]

Algoritmos de Ordenao em Java

Finalizado
o processo de separao ento chamado um prprio mtodo quickSort() de forma
recursiva, onde ele far o
processo de separao interna dentro da sublista e
assim ser feito at que todos os elementos estejam ordenados.

Se
voc preferir, na Listagem 4 tambm temos
um pseudocdigo que exemplifica o funcionamento do QuickSort em
linguagem
genrica.

Listagem
4. Pseudocdigo quicksort

procedimento QuickSort(X[], IniVet, FimVet)


var
i, j, pivo, aux
incio
i <- IniVet
j <- FimVet
pivo <- X[(IniVet + FimVet) div 2]
enquanto(i < j)
|

enquanto (X[i] < pivo) faa

i <- i + 1

fimEnquanto

enquanto (X[j] > pivo) faa

j <- j - 1

fimEnquanto

se (i <= j) ento

aux

X[i] <- X[j]

<- X[i]

X[j] <- aux

i <- i + 1

j <- j - 1

fimSe

fimEnquanto
se (j > IniVet) ento
|

QuickSort(X, IniVet, j)

fimSe
se (i < FimVet) ento
|

QuickSort(X, i, FimVet)

fimse
fimprocedimento

O
QuickSort um algoritmo mais robusto e complexo que os mostrados anteriormente,
por isso achamos importante
exemplificar o seu uso atravs do pseudocdigo.

Vejamos
na Tabela 3 a comparao entre o
tempo de execuo.

QuickSort

Elementos

Caso mdio
(nlogn)

100

0 ms

1.000

0 ms

10.000

39 ms

http://www.devmedia.com.br/algoritmos-de-ordenacao-em-java/32693[30/06/2015 11:33:59]

Algoritmos de Ordenao em Java

100.000

43 ms

200.000

50 ms

Tabela
3. Medio do Tempo de execuo para QuickSort

Veja
que o tempo de processamento do QuickSort muito bom quando tratamos do caso
mdio, que exatamente o nosso
caso (randmico). Veja que o tempo para 200.000
registros muito eficiente, muito mais que os mostrados anteriormente
para
este tipo de caso.

Com
isso, vimos que em se tratando de simplicidade, o BubbleSort o melhor, visto
que sua implementao e lgica so
simples e eficazes para uma pequena
quantidade de valores, porm precisamos de algoritmos mais robustos quando

sabemos que a entrada se dar para uma grande quantidade de valores.

Por
outro lado, o InsertionSort no to complexo quanto o QuickSort, mas tambm
no to simples quanto o BubbleSort,
acrescentando um pouco mais de robustez
e consequentemente desempenho na ordenao de valores. O InsertionSort
um
meio termo e possibilita a ordenao de valores um pouco maiores que o
BubbleSort, mas tambm no consegue
ordenar uma grande quantidade de valores
igual ao QuickSort, que por sua vez, mostrou-se o algoritmo mais rpido de

todos e consequentemente o mais complexo de ser implementado. Isso ocorre


principalmente pelo fato de ele trabalhar
com recursos como recursividade para
alcanar um desempenho notvel.

perceptvel que o QuickSort, BubbleSort e InsertionSort possuem quase o mesmo


tempo de resposta quando estamos
tratando com at 1000 elementos no vetor, a variao
to insignificante que a escolha de um destes algoritmos mais
uma questo
pessoal do que profissional.

Ao
trabalhar com uma quantidade de valores maior, j percebemos que algoritmos
simples podem no ser a melhor
escolha, voc mesmo pode fazer um teste tentando
executar o BubbleSort para um milho de elementos. Se para 200.000
elementos o
tempo de resposta foi quase 82 segundos e o mesmo cresce de forma exponencial,
ento para um milho de
elementos possivelmente chegar perto ou passar
(dependendo do hardware) de horas.

Testamos
de forma exaustiva o algoritmo QuickSort para o melhor caso com 100 elementos
no vetor, e constatamos que
em alguns momentos ocorrem alguns picos de
velocidade onde o retorno muda de 1ms para 5ms, apontando uma pequena
perda de
desempenho. Testando a mesma quantidade de elementos para o melhor caso no
BubbleSort a varivel no
ocorreu nenhuma vez, mantendo a velocidade sempre em
1ms. Apontando um ponto positivo para o algoritmo mais simples
em casos
especficos.

Ronaldo Lanhellas
Bacharel em Cincia da Computao (UNAMA). Cursando Ps-Graduao em Tecnologias WEB (UFPA). Trabalhando atualmente como Analista de
Sistemas Java.

http://www.devmedia.com.br/algoritmos-de-ordenacao-em-java/32693[30/06/2015 11:33:59]

Algoritmos de Ordenao em Java

Publicado em 2015

O que voc achou deste


post?
Gostei
(3)

(0)

Mais contedo sobre Java

Todos os comentarios (4)

Postar dvida / Comentrio

Meus comentarios

Wellington Dantas Pereira

MVP

Muito interessante, mas como eu descubro o tempo que o algoritmo levou para ordenar meu array? **utilizo o netbeans

[h +1 ms] - Responder

Douglas Claudio
Ol Wellington, obrigado pelo seu comentrio.
Enviamos sua solicitao ao Ronaldo e estamos no aguardo de um feedback do mesmo.
Um abrao.

[h +1 ms] - Responder

Wellington Dantas Pereira

MVP

haha obrigado pela ateno, mas no h mais necessidade.

Consegui entender o funcionamento, faltou mesmo foi ateno da minha parte rs.

Caso alguem tenha a mesma dvida, basta se atentar na utilizao do System.currentTimeMillis().

[h +1 ms] - Responder

Douglas Claudio
Ol Wellington,
Qualquer problema conte conosco e obrigado por compartilhar a sua soluo.

Um abrao.

[h +1 ms] - Responder

Publicidade

http://www.devmedia.com.br/algoritmos-de-ordenacao-em-java/32693[30/06/2015 11:33:59]

Algoritmos de Ordenao em Java

Mais posts
Artigo

Introduo ao Facelets

JAVA

JSF

Artigo

Conhea o conceito Mnada no Java

JAVA

Artigo

Programao Orientada a Objetos versus Programao Estruturada

JAVA

Artigo

Raspberry Pi e a biblioteca Java RxTx

JAVA

RASPBERRY

JAVA

JPA

RXTX

Artigo

CRUD completo com Hibernate e JPA

CRUD

HIBERNATE

Artigo

Baixo Acoplamento com DAO

JAVA

DAO

Artigo

Programao Restritiva: usando boas prticas em Java


Artigo

Conhea a Arquitetura Lambda em Java

JAVA

Artigo

Profiling: Como analisar Aplicaes Java

http://www.devmedia.com.br/algoritmos-de-ordenacao-em-java/32693[30/06/2015 11:33:59]

JAVA

LAMBDA

BIGDATA

JAVA

BOAS PRATICAS

.NET

PROGRAMAO

Algoritmos de Ordenao em Java

Listar mais contedo

Anuncie | Loja | Publique | Assine | Fale conosco

Hospedagem web por Porta 80 Web


Hosting

http://www.devmedia.com.br/algoritmos-de-ordenacao-em-java/32693[30/06/2015 11:33:59]

You might also like