Você está na página 1de 6

PROJETO E ANÁLISE DE ALGORITMOS

Análise da Ordenação
Alice Cabral1 e Juliana Silvestre1
1
Instituto de Ciências Exatas e Informática –
Pontifı́cia Universidade Católica de Minas Gerais (PUCMG)
Belo Horizonte – MG – Brasil

alicecamarques@gmail.com

juliana.silvestresilva@hotmail.com

Neste trabalho, é apresentada a implementação de 3 métodos de ordenação


(Seleção, Quicksort e Bubblesort) e um método que encontra todas as permutações de
um array. Após a implementação, foi contabilizada a quantidade de comparações real-
izadas por cada algoritmo, considerando vetores com 100, 1.000 e 1000.000 elementos,
assim como o tempo de execução de cada um.
Para melhor organização, a implementação do código de cada algoritmo e sua
respectiva explicação foi dividida igualmente entre as duas alunas. A Alice ficou re-
sponsável pelos métodos Quicksort e Bubblesort e a Juliana pelos métodos Seleção e
Permutações. A análise dos custos computacionais de todos os algoritmos implementa-
dos foi feita em conjunto pelas duas alunas.

1. Seleção
O algoritmo de seleção realiza a ordenação do vetor baseando-se em buscar o menor
valor e passá-lo para a primeira posição do vetor, em seguida o segundo menor valor
para a segunda posição e assim sucessivamente, até a última posição. Para isso, um
número é escolhido a partir da primeira posição do vetor e este é comparado com os
demais elementos a sua direita, sendo que se for encontrado um valor menor é feita a
troca de posição dos dois valores. Tal processo, portanto, é repetido até que o vetor esteja
ordenado.

1.1. Implementação
1 # i n c l u d e < s t d i o . h>
2 # i n c l u d e < s t d l i b . h>
3
4 void selecao ( i n t * array , i n t n ) {
5 i n t numComparacoes = 0 ;
6 f o r ( i n t i = 0 ; i < ( n − 1 ) ; i ++) {
7 i n t menor = i ;
8 f o r ( i n t j = ( i + 1 ) ; j < n ; j ++) {
9 numComparacoes ++;
10 i f ( a r r a y [ menor ] > a r r a y [ j ] ) {
11 menor = j ;
12 }
13 }
14 swap ( a r r a y , menor , i ) ;
15 }
16 p r i n t f ( ” Numero de c o m p a r a c o e s : %d ” , numComparacoes ) ;
17 }
Listing 1. Código fonte seleção em C

1.2. Análise dos Custos Computacionais


A complexidade do algoritmo de Seleção, para todos os casos, é dada pela seguinte
recorrência:
T (n) = T (n − 1) + n − 1
Portanto, a complexidade desse algoritmo é

T (n) = O(n2 )

A tabela 1 mostra o tempo prático (tempo de execução) e o tempo prático (nº de


comparações) para as instâncias de tamanhos diferentes.
A partir disso, conclui-se que o algoritmo de Seleção não é considerado eficiente
para grandes entradas e realiza 0(n²) comparações.

Table 1.
SELEÇÃO
Tamanho do array Tempo de execução (ms) Nº de comparações
100 0,0698 4950
1000 5,6664 499500
10000 545,1068 49995000

2. Quicksort
O algoritmo quicksort baseia-se na divisão do vetor em duas partes para realizar a
ordenação. Para isso, é escolhido um elemento, chamado de pivô, e este é comparado com
os demais de modo que todos os valores menores que ele são armazenados no primeiro
subvetor e os elementos maiores no segundo subvetor. Ao final deste processo o elemento
do pivô já estará em sua posição final e os subvetores serão ordenados recursivamente até
q todo vetor esteja em ordem crescente.

2.1. Implementação
1 # i n c l u d e < s t d i o . h>
2 # i n c l u d e < s t d l i b . h>
3 i n t numComparacoes = 0 ;
4 i n t p a r t i t i o n ( i n t * a r r a y , i n t n , c o n s t i n t esq , c o n s t i n t d i r ) {
5 i n t i = esq ;
6 f o r ( i n t j = e s q ; j < d i r ; j ++) {
7 numComparacoes ++;
8 i f ( a r r a y [ j ] <= a r r a y [ d i r ] ) {
9 swap ( a r r a y , i ++ , j ) ;
10 }
11 }
12 swap ( a r r a y , i , d i r ) ;
13 return i ;
14 }
15
16 v o i d q u i c k s o r t ( i n t * a r r a y , i n t n , c o n s t i n t esq , c o n s t i n t d i r ) {
17 i f ( e s q >= d i r ) r e t u r n ;
18 i n t p i v o = p a r t i t i o n ( a r r a y , n , esq , d i r ) ;
19

20 q u i c k s o r t ( a r r a y , n , esq , p i v o − 1 ) ;
21 q u i c k s o r t ( array , n , pivo + 1 , d i r ) ;
22 }
23
24 void imprimirNumComparacoesQuicksort ( ) {
25 p r i n t f ( ” \ nNumero de c o m p a r a c o e s : %d ” , numComparacoes ) ;
26 }
Listing 2. Código fonte quicksort em C

2.2. Análise dos Custos Computacionais


No melhor caso do Quicksort, quando o pivô escolhido divide o vetor em dois subvetores
de tamanho iguais a n/2, a complexidade é dada pela seguinte recorrência:

T (n) = 2T (n/2) + n − 1

Portanto, no melhor caso,


T (n) = O(nlogn)
No pior caso, quando o pivô divide o vetor em dois subvetores, um com zero elemento e
outro com n – 1 elementos, a recorrência é:

T (n) = T (n − 1) + n − 1

Portanto, no pior caso,


T (n) = O(n2 )

A tabela 2 mostra o tempo prático (tempo de execução) e o tempo prático (nº de


comparações) para as instâncias de tamanhos diferentes.
Conclui-se que o Quicksort é um algoritmo extremamente eficiente e faz em média
O(nlogn) comparações, apesar de que seu pior caso para comparações é quadrático.

Table 2.
QUICKSORT
Tamanho do array Tempo de execução (ms) Nº de comparações
100 0,0314 897
1000 0,3725 13138
10000 4,5072 176065
3. Bubblesort
O Bubblesort utiliza a comparação dos elementos, de dois em dois, para realizar a
ordenação do vetor. Neste algoritmo, cada elemento é comparado com seu sucessor,
ou seja, o elemento contido na posição j é comparado ao elemento em j+1, caso estes
não estejam em ordem crescente é feita a troca entre esses dois elementos. Tal processo,
portanto, é repetido até que o vetor esteja ordenado.
3.1. Implementação
1 # i n c l u d e < s t d i o . h>
2 # i n c l u d e < s t d l i b . h>
3
4 void b u bb le s or t ( i n t * array , i n t n ) {
5 i n t temp , numComparacoes = 0 ;
6 f o r ( i n t i = 1 ; i < n ; i ++) {
7 f o r ( i n t j = 0 ; j < n − 1 ; j ++) {
8 numComparacoes ++;
9 if ( array [ j ] > array [ j + 1]) {
10 temp = a r r a y [ j ] ;
11 array [ j ] = array [ j +1];
12 a r r a y [ j + 1 ] = temp ;
13 }
14 }
15 }
16 p r i n t f ( ” Numero de c o m p a r a c o e s : %d ” , numComparacoes ) ;
17 }
Listing 3. Código fonte bubblesort em C

3.2. Análise dos Custos Computacionais


A complexidade do Bubblesort, em todos os casos, é dada pela seguinte recorrência:
T (n) = T (n − 1) + n − 1
Portanto, a complexidade desse algoritmo é
T (n) = O(n2 )

A tabela 3 mostra o tempo prático (tempo de execução) e o tempo prático (nº de


comparações) para as instâncias de tamanhos diferentes.
A partir disso, conclui-se que o Bubblesort não é um algoritmo muito eficiente e
faz o mesmo número de comparações para todos os casos.

4. Permutações
A permutação de um vetor de n elementos envolve encontrar todas as possı́veis
combinações de seus elementos, de modo que, ao final, cada número tenha passado por
todas as posições do vetor. O algoritmo para encontrar todas as permutações parte do
ı́ndice recebido ate a última posição do vetor e, dentro desse laço de iteração, é feito um
swap das posições do ı́ndice da iteração atual e do ı́ndice recebido pela função. Após isso,
há uma chamada recursiva, que vai aumentando o ı́ndice de controle em 1 unidade. Após
essa chamada, o swap é realizado novamente. Por fim, quando o ı́ndice de controle tem
valor igual ao ı́ndice da última posição do array (n 1), a permutação é exibida na saı́da
padrao.
Table 3.
BUBBLESORT
Tamanho do array Tempo de execução (ms) Nº de comparações
100 0,1596 5050
1000 16,6730 500500
10000 1455,9734 50005000

4.1. Implementação
1 # i n c l u d e < s t d i o . h>
2 # i n c l u d e < s t d l i b . h>
3 i n t numPermutacoes = 0 ;
4 void permutacoes ( i n t * a r r a y , i n t i n i c i o , i n t fim )
5 {
6 i f ( i n i c i o == f i m )
7 {
8 n u m P e r m u t a c o e s ++;
9 }
10 else
11 {
12 f o r ( i n t i = i n i c i o ; i <= f i m ; i ++)
13 {
14 swap ( a r r a y , i n i c i o , i ) ;
15 permutacoes ( a r r a y , i n i c i o + 1 , fim ) ;
16 swap ( a r r a y , i n i c i o , i ) ;
17 }
18 }
19 }
20 void imprimirQntPermutacoes ( )
21 {
22 p r i n t f ( ” Numero de p e r m u t a c o e s : %d ” , n u m P e r m u t a c o e s ) ;
23 }
Listing 4. Código fonte permutações em C

4.2. Análise dos Custos Computacionais


Considerando n como o tamanho do vetor, é possı́vel concluir que o número de
permutações é igual a n!. Cada permutação necessita de um tempo de O(n), portanto,
a complexidade desse algoritmo é O(n*n!).
A tabela 4 mostra o tempo prático (tempo de execução) e o tempo prático (nº de
comparações) para as instâncias de tamanhos diferentes.
Table 4.
PERMUTAÇÕES
Tamanho do array Tempo de execução (ms) Nº de comparações
4 0,003 24
7 0,069 5040
10 38,867 3628800

Você também pode gostar