1. Universidade Federal de Ouro Preto
Instituto de Ciências Exatas e Biológicas
Departamento de Computação
ALGORITMOS E ESTRUTURAS DE DADOS
Quinto Trabalho Prático
Johnnatan Messias Peixoto Afonso
Professor - David Menotti
Monitor - Kayran dos Santos
Monitor - Pedro Ismar Silva Souto
Ouro Preto
4 de dezembro de 2009
5. 1 Introdução
Esse trabalho consiste na análise dos algoritmos de ordenação para avaliar o
número de comparações, bem como o número de atribuições e também o tempo
de relógioque cada algoritmo em diferentes elementos e métodos de ordenação dos
vetores:
• Random - Os elementos do vetor foram introduzidos de forma aleatória, ou
seja, estando, portanto, desordenado;
• Sorted - Os elementos do vetor estão ordenados;
• Almost Sorted - Os elementos do vetor estão quase ordenados;
• Inverted - Os elementos do vetor estão de forma ordenada invertida.
Assim, para os testes de ordenação, foram utilizados os seguintes métodos de or-
denação: QuickSort, QuickSort Otimizado, HeapSort, HeapSort Otimizado, Merge-
Sort, Mergesort Otimizado, SelectSort, SelectSort Otimizado, InsertSort, InsertSort
com o elemento Sentinela, InsertSort implementado através de cursores, BubbleSort
e BubbleSort com Troca.
1.1 Considerações iniciais
• Ambiente de desenvolvimento do código fonte: Microsoft Visual Studio 2008
Professional.
• Linguagem utilizada: Linguagem C.
• Para os testes, utilizei um notebook rodando o Microsoft Windows 7 Profes-
sional 64 bits, com a seguinte conguração: Proc. Turion MK-36, 2GB RAM,
portanto o tempo de relógiodos testes será diferente quando o programa for
executado em outro computador com uma conguração diferente da citada
anteriormente.
• Ambiente de desenvolvimento da documentação: TeXnicCenter 1.0 SRC-Editor
de LATEX.
1.2 Especicação do problema
O objetivo deste trabalho é analisar algoritmos de ordenação por comparação e
suas variações e otimizações. Essa análise será dividida em duas partes.
Na primeira, a análise será sobre os algoritmos de ordenação simples (de ordem de
complexidade O(n2) - i.e., BubbleSort, SelectSort, InsertSort e algumas variações).
Você deverá implementar os três algoritmos citados e implementar variações desses
algoritmos de forma que através de análises de experimentos você possa analisar:
• Se vale a pena inserir a vericação de ordenação (houve troca) no algoritmo
BubbleSort;
• Se vale a pena usar o algoritmo InsertSort com elemento sentinela;
1
6. • Se vale a pena inserir uma vericação (Min == i) para evitar a troca, no
método SelectSort.
A segunda parte será sobre os algoritmos de ordenação por comparação ditos
ecientes, como MergeSort, HeapSort e QuickSort, que tem complexidade de tempo
de O( n log n ). São fornecidas implementações convencionais e versões otimizadas.
Aproveite os algoritmos implementados por você e verique:
• Até que tamanho de entrada, vale a pena usar algoritmos O(n2) com relação
a algoritmos O(n log n).
2 Algoritmo e estruturas de dados
Foi selecionado o TAD, Tipo Abstrato de Dados, Sort.h para representar as im-
plementações dos algoritmos de ordenação citados na introdução deste documento.
2.1 TAD - Sort
Para representar as implementações dos algoritmos de ordenação foi criado um
TAD Sort.h
2.1.1 Assinatura das funções
Abaixo as assinaturas do Sort.h.
#include Array . h
//Funções de ordenação agrupadas
void Q u i c k S o r t ( TArray ∗ , double∗ , double∗ ) ;
5 void QuickSortO ( TArray ∗ , double∗ , double∗ ) ;
void HeapSort ( TArray ∗ , double∗ , double∗ ) ;
void HeapSortO ( TArray ∗ , double∗ , double∗ ) ;
10 void M e r g e S o r t ( TArray ∗ , double∗ , double∗ ) ;
void MergeSortO ( TArray ∗ , double∗ , double∗ ) ;
void B u b b l e S o r t ( TArray ∗ , double∗ , double∗ ) ;
void BubbleSortT ( TArray ∗ , double∗ , double∗ ) ;
15
void S e l e c t S o r t ( TArray ∗ , double∗ , double∗ ) ;
void S e l e c t S o r t O ( TArray ∗ , double∗ , double∗ ) ;
void I n s e r t S o r t ( TArray ∗ , double∗ , double∗ ) ;
20 void I n s e r t S o r t O S ( TArray ∗ , double∗ , double∗ ) ;
Programa 1: Assinaturas do Sort
2.1.2 QuickSort
Esse método de ordenação tem por nalidade dividir um problema em 2 sub-
problemas de modo que facilite a resolução desses subproblemas e assim quando
juntar as soluções desses subproblemas teremos um problema maior solucionado,
2
7. isto é, ordenado. Esse algoritmo talvez seja o mais utilizado atualmente devido a
sua eciência em ordenação para um tamanho variável de elementos. Além disso,
selecionamos um pivô, elemento para servir como base, ou seja, comparação com os
outros elementos para dividir os problemas, onde os elementos à esquerda do pivô
sejam menores que os da direita. Obs.: Ele não é estável e majoritariamente sua
ordem de complexidade é O(nlog(n)).
// QuickSort
void P a r t i t i o n ( int l e f t , int r i g h t , int ∗ i , int ∗j , TArray ∗pA , double ∗NAt ,
double ∗NComp)
{
TItem p i v o t , Aux ;
5
∗ i= l e f t ; ∗ j=r i g h t ;
( ∗NComp) +=4;
if ( ( ( pA−P o s i t i o n s [ l e f t ] . key pA−P o s i t i o n s [ r i g h t ] . key ) (pA−
P o s i t i o n s [ l e f t ] . key pA−P o s i t i o n s [ ( r i g h t+ l e f t ) / 2 ] . key ) ) | |
10 ( ( pA−P o s i t i o n s [ l e f t ] . key pA−P o s i t i o n s [ r i g h t ] . key ) (pA−
P o s i t i o n s [ l e f t ] . key pA−P o s i t i o n s [ ( r i g h t+ l e f t ) / 2 ] . key ) ) )
{
p i v o t = pA−P o s i t i o n s [ l e f t ] ; ( ∗ NAt ) ++;
}
else
15 {
( ∗NComp) +=4;
if ( ( ( pA−P o s i t i o n s [ l e f t ] . key pA−P o s i t i o n s [ r i g h t ] . key ) (pA−
P o s i t i o n s [ r i g h t ] . key pA−P o s i t i o n s [ ( r i g h t+ l e f t ) / 2 ] . key ) ) | |
( ( pA−P o s i t i o n s [ l e f t ] . key pA−P o s i t i o n s [ r i g h t ] . key ) (pA−
P o s i t i o n s [ r i g h t ] . key pA−P o s i t i o n s [ ( r i g h t+ l e f t ) / 2 ] . key ) ) )
{
20 p i v o t = pA−P o s i t i o n s [ r i g h t ] ; ( ∗ NAt) ++;
}
else
{
p i v o t = pA−P o s i t i o n s [ ( r i g h t+ l e f t ) / 2 ] ; ( ∗NAt) ++;
25 }
}
do
{
while( p i v o t . keypA−P o s i t i o n s [ ∗ i ] . key )
30 {
( ∗NComp) ++;
( ∗ i ) ++;
}
while( p i v o t . keypA−P o s i t i o n s [ ∗ j ] . key )
35 {
( ∗NComp) ++;
( ∗ j ) −−;
}
if( ∗ i =∗j )
40 {
Aux=pA−P o s i t i o n s [ ∗ i ] ; ( ∗ NAt) ++;
pA−P o s i t i o n s [ ∗ i ]=pA−P o s i t i o n s [ ∗ j ] ; ( ∗ NAt ) ++;
pA−P o s i t i o n s [ ∗ j ]=Aux ; ( ∗NAt) ++;
( ∗ i ) ++;
45 ( ∗ j ) −−;
}
3
8. } while( ∗ i =∗j ) ;
}
50 void S o r t ( int l e f t , int r i g h t , TArray ∗pA , double ∗NAt , double ∗NComp)
{
int i , j ;
P a r t i t i o n ( l e f t , r i g h t , i , j , pA , NAt , NComp) ;
if( l e f t j )
55 S o r t ( l e f t , j , pA , NAt , NComp) ;
if( i r i g h t )
S o r t ( i , r i g h t , pA , NAt , NComp) ;
}
60 void Q u i c k S o r t ( TArray ∗pA , double ∗NAt , double ∗NComp)
{
S o r t ( 0 , pA−S i z e −1 ,pA , NAt , NComp) ;
}
Programa 2: QuickSort
2.1.3 QuickSort Otimizado
Para aperfeiçoar o QuickSort, só usamos o QuickSort para ordenar mais do que 20
elementos, caso a quantidade de elementos seja menor, então chamamos o método
SelectSort e ainda vericamos se para que evite usar o maior elementos ou dos
extremos como pivô. Assim haverá uma melhora signicativa no tempo de execução.
// QuickSortO
void QuickSortO ( TArray ∗pA , double ∗NAt , double ∗NComp)
{
int i , j ;
5 T Pi l ha S t a c k ;
TItemPAD l i m i t s , l i m i t s A u x ;
int MaxStack = ( int) ( 2 . ∗ ( l o g ( ( float)pA−S i z e ) / l o g ( 2 . ) ) ) ;
FPVazia( Sta ck , MaxStack ) ;
10
l i m i t s . l e f t = 0 ;
l i m i t s . r i g h t = pA−S i z e −1;
while( 1 )
15 {
if ( ( l i m i t s . r i g h t − l i m i t s . l e f t +1) 2 0 )
{
// Partition
TItem p i v o t , Aux ;
20 i=l i m i t s . l e f t ; j=l i m i t s . r i g h t ;
( ∗NComp) +=4;
if ( ( ( pA−P o s i t i o n s [ l i m i t s . l e f t ] . key pA−P o s i t i o n s [ l i m i t s . r i g h t
] . key ) (pA−P o s i t i o n s [ l i m i t s . l e f t ] . key pA−P o s i t i o n s [ (
l i m i t s . r i g h t+l i m i t s . l e f t ) / 2 ] . key ) ) | |
( ( pA−P o s i t i o n s [ l i m i t s . l e f t ] . key pA−P o s i t i o n s [ l i m i t s . r i g h t ] .
key ) (pA−P o s i t i o n s [ l i m i t s . l e f t ] . key pA−P o s i t i o n s [ (
l i m i t s . r i g h t+l i m i t s . l e f t ) / 2 ] . key ) ) )
{
25 p i v o t = pA−P o s i t i o n s [ l i m i t s . l e f t ] ; ( ∗ NAt ) ++;
}
4
9. else
{
( ∗NComp) +=4;
30 if ( ( ( pA−P o s i t i o n s [ l i m i t s . l e f t ] . key pA−P o s i t i o n s [ l i m i t s .
r i g h t ] . key ) (pA−P o s i t i o n s [ l i m i t s . r i g h t ] . key pA−
P o s i t i o n s [ ( l i m i t s . r i g h t+l i m i t s . l e f t ) / 2 ] . key ) ) | |
( ( pA−P o s i t i o n s [ l i m i t s . l e f t ] . key pA−P o s i t i o n s [ l i m i t s .
r i g h t ] . key ) (pA−P o s i t i o n s [ l i m i t s . r i g h t ] . key pA−
P o s i t i o n s [ ( l i m i t s . r i g h t+l i m i t s . l e f t ) / 2 ] . key ) ) )
{
p i v o t = pA−P o s i t i o n s [ l i m i t s . r i g h t ] ; ( ∗ NAt) ++;
}
35 else
{
p i v o t = pA−P o s i t i o n s [ ( l i m i t s . r i g h t+l i m i t s . l e f t ) / 2 ] ; ( ∗NAt) ++;
}
}
40
do
{
while( p i v o t . keypA−P o s i t i o n s [ i ] . key )
{
45 ( ∗NComp) ++;
i ++;
}
while( p i v o t . keypA−P o s i t i o n s [ j ] . key )
{
50 ( ∗NComp) ++;
j −−;
}
if( i =j )
{
55 Aux=pA−P o s i t i o n s [ i ] ; ( ∗ NAt ) ++;
pA−P o s i t i o n s [ i ]=pA−P o s i t i o n s [ j ] ; ( ∗ NAt) ++;
pA−P o s i t i o n s [ j ]=Aux ; ( ∗NAt ) ++;
i ++;
j −−;
60 }
} while( i =j ) ;
// Partition
if ( l i m i t s . l e f t j )
65 {
if ( i l i m i t s . r i g h t )
{
l i m i t s A u x . l e f t = i ;
l i m i t s A u x . r i g h t = l i m i t s . r i g h t ;
70 PEmpilha( Sta ck , l i m i t s A u x ) ;
}
// l i m i t s . l e f t = l i m i t s . l e f t ;
l i m i t s . r i g h t = j ;
}
75 else if ( i l i m i t s . r i g h t )
{
l i m i t s . l e f t = i ;
// l i m i t s . r i g h t = l i m i t s . r i g h t ;
}
80 else
5
10. {
if ( ! PEhVazia( S t a c k ) )
PDesempilha( St ack , l i m i t s ) ;
else
85 break;
}
}
else
{
90 // SelectSort
int Min ;
TItem aux ;
for ( i = l i m i t s . l e f t ; i l i m i t s . r i g h t ; i ++)
{
95 Min = i ;
for ( j = i + 1 ; j = l i m i t s . r i g h t ; j ++)
{
( ∗NComp) ++;
if ( pA−P o s i t i o n s [ j ] . key pA−P o s i t i o n s [ Min ] . key )
100 Min = j ;
}
aux = pA−P o s i t i o n s [ Min ] ; ( ∗NAt) ++;
pA−P o s i t i o n s [ Min ] = pA−P o s i t i o n s [ i ] ; ( ∗NAt) ++;
pA−P o s i t i o n s [ i ] = aux ; ( ∗NAt ) ++;
105 }
if ( ! PEhVazia( S t a c k ) )
PDesempilha( St ack , l i m i t s ) ;
else
break;
110 }
}
P L i b e r a ( S t a c k ) ;
}
Programa 3: QuickSort-O
2.1.4 HeapSort
Baseia-se na construção de heaps que para a ordenação dos elementos, onde
trocando o elemento da posição inicial para a posição n, depois refazemos o heap
para os próximos item até que os elementos estejam ordenados.
// HeapSort
void RemakeHeap ( int l e f t , int r i g h t , TArray ∗pA , double ∗NAt , double ∗
NComp)
{
5 int i = l e f t , j ;
TItem aux ;
j = i ∗ 2 + 1 ;
aux = pA−P o s i t i o n s [ i ] ; ( ∗ NAt ) ++;
while ( j = r i g h t )
10 {
if ( j r i g h t )
{
( ∗NComp) ++;
if (pA−P o s i t i o n s [ j ] . key pA−P o s i t i o n s [ j + 1 ] . key )
6
11. 15 j ++;
}
( ∗NComp) ++;
if ( aux . key = pA−P o s i t i o n s [ j ] . key )
break;
20 pA−P o s i t i o n s [ i ] = pA−P o s i t i o n s [ j ] ; ( ∗ NAt) ++;
i = j ;
j = i ∗ 2 + 1 ;
}
pA−P o s i t i o n s [ i ] = aux ; ( ∗NAt ) ++;
25 }
void MakeHeap ( TArray ∗pA , double ∗NAt , double ∗NComp)
{
int l e f t ;
30 l e f t = pA−S i z e / 2 ;
while ( l e f t = 0 )
{
RemakeHeap ( l e f t , pA−S i z e −1 , pA , NAt , NComp) ;
l e f t −−;
35 }
}
void HeapSort ( TArray ∗pA , double ∗NAt , double ∗NComp)
{
40 int l e f t , r i g h t ;
TItem aux ;
MakeHeap (pA , NAt , NComp) ;
l e f t = 0 ; r i g h t = pA−S i z e −1;
while ( r i g h t = 0 )
45 {
aux = pA−P o s i t i o n s [ 0 ] ; ( ∗ NAt) ++;
pA−P o s i t i o n s [ 0 ] = pA−P o s i t i o n s [ r i g h t ] ; ( ∗ NAt) ++;
pA−P o s i t i o n s [ r i g h t −−] = aux ; ( ∗NAt) ++;
RemakeHeap ( l e f t , r i g h t , pA , NAt , NComp) ;
50 }
}
Programa 4: HeapSort
2.1.5 HeapSort Otimizado
Utiliza-se a versão não interativa, isto é, sem recursividade, para a ordenação
dos elementos.
// HeapSortO
void HeapSortO ( TArray ∗pA , double ∗NAt , double ∗NComp)
{
int i , j ;
5 int l e f t , r i g h t ;
TItem aux ;
// MakeHeap
l e f t = pA−S i z e / 2 ;
r i g h t = pA−S i z e −1;
10 while ( l e f t = 0 )
{
// RemakeHeap
i = l e f t ;
7
12. j = i ∗ 2 + 1 ;
15 aux = pA−P o s i t i o n s [ i ] ; ( ∗ NAt) ++;
while ( j = r i g h t )
{
if ( j r i g h t )
{
20 ( ∗NComp) ++;
if (pA−P o s i t i o n s [ j ] . key pA−P o s i t i o n s [ j + 1 ] . key )
j ++;
}
( ∗NComp) ++;
25 if ( aux . key = pA−P o s i t i o n s [ j ] . key )
break;
pA−P o s i t i o n s [ i ] = pA−P o s i t i o n s [ j ] ; ( ∗ NAt ) ++;
i = j ;
j = i ∗ 2 + 1 ;
30 }
pA−P o s i t i o n s [ i ] = aux ; ( ∗NAt) ++;
// RemakeHeap
l e f t −−;
}
35 // MakeHeap
l e f t = 0 ; r i g h t = pA−S i z e −1;
while ( r i g h t = 0 )
{
40 aux = pA−P o s i t i o n s [ 0 ] ; ( ∗ NAt) ++;
pA−P o s i t i o n s [ 0 ] = pA−P o s i t i o n s [ r i g h t ] ; ( ∗ NAt) ++;
pA−P o s i t i o n s [ r i g h t −−] = aux ; ( ∗NAt) ++;
// RemakeHeap
i = l e f t ;
45 j = i ∗ 2 + 1 ;
aux = pA−P o s i t i o n s [ i ] ; ( ∗ NAt) ++;
while ( j = r i g h t )
{
if ( j r i g h t )
50 {
( ∗NComp) ++;
if (pA−P o s i t i o n s [ j ] . key pA−P o s i t i o n s [ j + 1 ] . key )
j ++;
}
55 ( ∗NComp) ++;
if ( aux . key = pA−P o s i t i o n s [ j ] . key )
break;
pA−P o s i t i o n s [ i ] = pA−P o s i t i o n s [ j ] ; ( ∗ NAt ) ++;
i = j ;
60 j = i ∗ 2 + 1 ;
}
pA−P o s i t i o n s [ i ] = aux ; ( ∗NAt) ++;
// RemakeHeap
}
65 }
Programa 5: HeapSort-O
8
13. 2.1.6 MergeSort
Consiste em dividir o problema em subproblemas, ou seja, em conjuntos, assim
ele ordena cada conjunto de maneira recursiva. Por nal, ele junta os conjuntos num
só onde o novo conjunto maior está ordenado, isto é, o problema em ordenar um
vetor está resolvido. Assim como o HeapSort, o MergeSort também é O(nlog(n)).
// MergeSort
void Merge ( TArray ∗pA , TArray ∗pAux , int i n i t 1 , int end1 , int i n i t 2 , int
end2 , double ∗NAt , double ∗NComp)
{
int i , j , k ;
5 F r e e A r r a y ( pAux ) ;
A l l o c a t e ( pAux , end2−i n i t 1 +1) ;
Copy (pA , pAux , i n i t 1 , end2 , NAt , NComp) ;
for ( i = 0 , j = end1−i n i t 1 +1 , k = i n i t 1 ; k = end2 ; k++)
{
10 if ( i == end1−i n i t 1 +1 )
{
pA−P o s i t i o n s [ k ] = pAux−P o s i t i o n s [ j ++]; ( ∗NAt) ++;
continue;
}
15 if ( j == end2−i n i t 2+end1−i n i t 1 +2 )
{
pA−P o s i t i o n s [ k ] = pAux−P o s i t i o n s [ i + + ] ; ( ∗NAt) ++;
continue;
}
20 ( ∗NComp) ++;
if ( pAux−P o s i t i o n s [ i ] . key pAux−P o s i t i o n s [ j ] . key )
{
pA−P o s i t i o n s [ k ] = pAux−P o s i t i o n s [ i + + ] ; ( ∗NAt) ++;
}
25 else
{
pA−P o s i t i o n s [ k ] = pAux−P o s i t i o n s [ j + + ] ; ( ∗NAt) ++;
}
}
30 F r e e A r r a y ( pAux ) ;
}
void MSDivide ( TArray ∗pA , TArray ∗ pAux , int i n i t , int end , double ∗NAt ,
double ∗NComp)
{
35 int mid ;
if ( end == i n i t )
return;
mid = ( i n i t + end ) / 2 ;
40 MSDivide (pA , pAux , i n i t , mid , NAt , NComp) ;
MSDivide (pA , pAux , mid+1 , end , NAt , NComp) ;
Merge (pA , pAux , i n i t , mid , mid+1 , end , NAt , NComp) ;
}
45 void M e r g e S o r t ( TArray ∗pA , double ∗NAt , double ∗NComp)
{
TArray ∗ pAux ;
pAux = ( TArray ∗) m a l l o c ( sizeof( TArray ) ) ;
9
14. 50 A l l o c a t e ( pAux , pA−S i z e ) ;
MSDivide (pA , pAux , 0 , pA−S i z e −1 ,NAt , NComp) ;
F r e e A r r a y ( pAux ) ;
f r e e ( pAux ) ;
55 }
Programa 6: MergeSort
2.1.7 Mergesort Otimizado
Utilizou-se a versão não interativa para a otimização deste algoritmo.
// MergeSortO
void MergeSortO ( TArray ∗pA , double ∗NAt , double ∗NComp)
{
TItem ∗VAux, ∗pVAux ;
5 int l 1 , l 2 , u1 , u2 , s i z e , n ;
int i , j , k ;
n = pA−S i z e ;
s i z e =1;
10 VAux = ( TItem ∗) m a l l o c ( sizeof( TItem ) ∗n ) ;
while( s i z e n )
{
l 1 =0;
k =0;
15 while( l 1+s i z e n )
{
l 2=l 1+s i z e ;
u1=l 2 −1;
20 if ( l 2+s i z e −1n )
u2 = l 2+s i z e −1;
else
u2 = n −1;
// merge
25 for( i = l 1 , j = l 2 ; i = u1 j = u2 ; k++ )
{
( ∗NComp) ++;
if(pA−P o s i t i o n s [ i ] . key=pA−P o s i t i o n s [ j ] . key )
{ VAux [ k ] = pA−P o s i t i o n s [ i ++]; ( ∗NAt) ++;}
30 else
{ VAux [ k ] = pA−P o s i t i o n s [ j ++]; ( ∗NAt) ++;}
}
for( ; i = u1 ; k++ )
{ VAux [ k ] = pA−P o s i t i o n s [ i ++]; ( ∗NAt ) ++;}
35 for( ; j = u2 ; k++ )
{ VAux [ k ] = pA−P o s i t i o n s [ j ++]; ( ∗NAt ) ++;}
// incrementando l1
l 1=u2 +1;
}
40 for( i = l 1 ; k n ; i++ )
{ VAux [ k++] = pA−P o s i t i o n s [ i ] ; ( ∗NAt ) ++;}
// copiando temp em x
// for ( i = 0 ; i n ; i++)
45 // pA−Positions [ i ] = VAux[ i ] ;
10
15. pVAux = VAux ;
VAux = pA−P o s i t i o n s ;
pA−P o s i t i o n s = pVAux ;
50 s i z e ∗=2;
}
f r e e (VAux) ;
}
Programa 7: Mergesort-O
2.1.8 SelectSort
Esse método possui ordem de complexidade de comparações O(n2) e realiza uma
troca por vez, selecionando menor elemento e trazendo-o para a primeira posição do
vetor.
Caso um determinado elemento numa posição seja menor que outro elemento na
posição min, então será realizada a troca desses elementos a m de tornar o vetor
ordenado.
// SelectSort
void S e l e c t S o r t ( TArray ∗ pA , double∗ NAt , double∗ NComp)
{
int i , j , Min ;
5 TItem aux ;
for ( i = 0 ; i pA−S i z e − 1 ; i ++)
{
Min = i ;
for ( j = i + 1 ; j pA−S i z e ; j ++)
10 {
( ∗NComp) ++;
if ( pA−P o s i t i o n s [ j ] . key pA−P o s i t i o n s [ Min ] . key )
{
Min = j ;
15 }
}
aux = pA−P o s i t i o n s [ Min ] ; ( ∗NAt) ++;
pA−P o s i t i o n s [ Min ] = pA−P o s i t i o n s [ i ] ; ( ∗NAt) ++;
pA−P o s i t i o n s [ i ] = aux ; ( ∗NAt ) ++;
20 }
}
Programa 8: SelectSort
2.1.9 SelectSort Otimizado
Para torná-lo mais eciente pois para fazer a troca antes vericamos se o Min é
diferente do i, caso seja verdadeira então realizamos a troca, uma vez que não era
necessário fazer essas operações quando o Min for igual ao i. Assim fazemos menos
atribuições e consequentemente diminuímos o tempo de execução do programa, o
que ajuda e muito para a ordenação de números grandes.
// SelectSort Otimizado
void S e l e c t S o r t O ( TArray ∗ pA , double∗ NAt , double∗ NComp)
{
11
16. int i , j , Min ;
5 TItem aux ;
for ( i = 0 ; i pA−S i z e − 1 ; i ++)
{
Min = i ;
for ( j = i + 1 ; j pA−S i z e ; j ++)
10 {
( ∗NComp) ++;
if ( pA−P o s i t i o n s [ j ] . key pA−P o s i t i o n s [ Min ] . key )
{
Min = j ;
15 }
}
if ( i != Min )
{
( ∗NComp) ++;
20 aux = pA−P o s i t i o n s [ Min ] ; ( ∗NAt ) ++;
pA−P o s i t i o n s [ Min ] = pA−P o s i t i o n s [ i ] ; ( ∗NAt) ++;
pA−P o s i t i o n s [ i ] = aux ; ( ∗NAt ) ++;
}
}
25 }
Programa 9: SelectSort-O
2.1.10 InsertSort
Esse método percorre o vetor da esquerda para a direita, vericando os novos
elementos se eles devem permanecer na mesma posição ou na anterior, e deixa os
elementos da esquerda ordenados.
// InsertSort
void I n s e r t S o r t ( TArray ∗ pA , double∗ NAt , double∗ NComp)
{
int i , j ;
5 TItem aux ;
for ( i = 1 ; i pA−S i z e ; i ++)
{
aux = pA−P o s i t i o n s [ i ] ; ( ∗NAt) ++;
j = i − 1 ; ( ∗NAt) ++;
10 while ( ( j = 0 ) ( aux . key pA−P o s i t i o n s [ j ] . key ) )
{
( ∗NComp) ++;
pA−P o s i t i o n s [ j + 1 ] = pA−P o s i t i o n s [ j ] ;
j −−; ( ∗NAt) ++;
15 }
pA−P o s i t i o n s [ j + 1 ] = aux ; ( ∗NAt ) ++;
}
}
Programa 10: InsertSort
2.1.11 InsertSort com o elemento Sentinela
Para isso utiliza-se o Sentinela, um registro na posição 0 do vetor que quando
j=0 indicará o m do loop, indicando que o vetor estará ordenado.
12
17. // InsertSort Otimizado com Sentinela
void I n s e r t S o r t O S ( TArray ∗ pA , double∗ NAt , double∗ NComp)
{
int i , j ;
5 TItem aux ;
for ( i = 2 ; i = pA−S i z e ; i ++)
{
aux = pA−P o s i t i o n s [ i ] ; ( ∗NAt) ++;
j = i − 1 ; ( ∗NAt) ++;
10 if( aux . keypA−P o s i t i o n s [ 0 ] . key )
{
( ∗NComp) ++;
pA−P o s i t i o n s [ 0 ] = aux ; /∗ s e n t i n e l a primeira posição pra
indicar q eu cheguei no fim do vetor ∗/
}
15 while ( aux . key pA−P o s i t i o n s [ j ] . key )
{
( ∗NComp) ++;
pA−P o s i t i o n s [ j +1] = pA−P o s i t i o n s [ j ] ; ( ∗NAt) ++;
j −−; ( ∗NAt ) ++;
20 }
pA−P o s i t i o n s [ j +1] = aux ; ( ∗NAt ) ++;
}
}
Programa 11: InsertSort-OS
2.1.12 InsertSort Implementado através de Cursores
Para isso utiliza-se uma lista por cursores que são inteiros que representam as
posições do arranjo, simulando os apontadores tradicionais.
// InsertSort com Cursores
void I n s e r t S o r t C ( TArray ∗ pA , double∗ NAt , double∗ NComp)
{
int i , j , Min ;
5
T L i s t a p L i s t a ;
FLVazia( p L i s t a , pA−S i z e , NAt , NComp) ;
for( i =0; i pA−S i z e ; i ++)
10 L I n s e r e ( p L i s t a , pA−P o s i t i o n s [ i ] , NAt , NComp) ;
L I n s e r e ( p L i s t a , pA−P o s i t i o n s [ i ] , NAt , NComp) ;
for( i =0; p L i s t a . tamanho 0; i ++)
LRPrimeiro ( p L i s t a ,pA−P o s i t i o n s [ i ] , NAt , NComp) ;
15 }
Programa 12: InsertSort-C
TAD da Lista por cursores
Para representar as implementações da lista por cursores foi criado um TAD
TLista.h bem como as assinaturas das funções:
typedef int Apontador ;
typedef int TChave ;
13
18. 5 typedef struct T C e l u l a {
TItem Item ;
Apontador pProx , pAnt ;
} T C e l u l a ;
10 typedef struct T L i s t a {
T C e l u l a ∗Item ;
Apontador T C e l u l a D i s p , p P r i m e i r o , pUltimo ;
int tamanho , n ;
} T L i s t a ;
15
void FLVazia ( T L i s t a ∗ , int , double∗ , double∗ ) ;
int Tamanho ( T L i s t a ∗ ) ;
int L I n s e r e ( T L i s t a ∗ , TItem pItem , double∗ , double∗ ) ;
void LRPrimeiro ( T L i s t a ∗ p L i s t a , TItem ∗ , double∗ , double∗ ) ;
20 void LRUltimo ( T L i s t a ∗ p L i s t a , TItem ∗ , double∗ , double∗ ) ;
Programa 13: TAD TLista.h
Implementação das funções da lista por cursores
Abaixo as implementações das funções desse TAD TLista.h
void FLVazia ( T L i s t a ∗ p L i s t a , int tam , double∗ NAt , double∗ NComp)
{
int i ;
p L i s t a −Item = ( T C e l u l a ∗ ) m a l l o c ( sizeof( T C e l u l a ) ∗tam ) ;
5 p L i s t a −tamanho = 0 ; ( ∗NAt) ++;
p L i s t a −p P r i m e i r o = −1; ( ∗NAt ) ++;
p L i s t a −pUltimo = −1; ( ∗NAt) ++;
p L i s t a −T C e l u l a D i s p = 0 ; ( ∗NAt) ++;
p L i s t a −n = tam ;
10 for ( i = 0 ; i tam ; i ++)
{
p L i s t a −Item [ i ] . pAnt = −1; ( ∗NAt ) ++;
p L i s t a −Item [ i ] . pProx = i + 1 ; ( ∗NAt) ++;
( ∗NComp) ++;
15 }
}
int Tamanho ( T L i s t a ∗ p L i s t a )
{
return( p L i s t a −tamanho ) ;
20 }
int L I n s e r e ( T L i s t a ∗ p L i s t a , TItem pItem , double∗ NAt , double∗ NComp)
{
int Pos , Disp , I n d i c e I n s e r c a o ;
if ( p L i s t a −tamanho == ( p L i s t a −n ) )
25 return 0 ;
( ∗NComp) ++;
Disp = p L i s t a −T C e l u l a D i s p ;
p L i s t a −T C e l u l a D i s p = p L i s t a −Item [ p L i s t a −T C e l u l a D i s p ] . pProx ;
p L i s t a −Item [ Disp ] . Item = pItem ;
30 p L i s t a −tamanho++; ( ∗NAt) ++;
if ( p L i s t a −tamanho == 1 )
{
p L i s t a −p P r i m e i r o = Disp ;
p L i s t a −pUltimo = p L i s t a −p P r i m e i r o ;
35 p L i s t a −Item [ p L i s t a −p P r i m e i r o ] . pProx = −1;
p L i s t a −Item [ p L i s t a −p P r i m e i r o ] . pAnt = −1;
14
19. return 1 ;
}
( ∗NComp) ++;
40 Pos = p L i s t a −p P r i m e i r o ;
if ( pItem . key p L i s t a −Item [ Pos ] . Item . key )
{
p L i s t a −Item [ Disp ] . pAnt = −1;
p L i s t a −Item [ Disp ] . pProx = Pos ;
45 p L i s t a −Item [ Pos ] . pAnt = Disp ;
p L i s t a −p P r i m e i r o = Disp ;
return 1 ;
}
( ∗NComp) ++;
50 I n d i c e I n s e r c a o = p L i s t a −Item [ Pos ] . pProx ;
while ( I n d i c e I n s e r c a o != −1 p L i s t a −Item [ I n d i c e I n s e r c a o ] . Item . key
pItem . key )
{
Pos = I n d i c e I n s e r c a o ; ( ∗NAt ) ++;
I n d i c e I n s e r c a o = p L i s t a −Item [ Pos ] . pProx ; ( ∗NAt) ++;
55 ( ∗NComp) ++;
}
if ( I n d i c e I n s e r c a o == −1)
{
p L i s t a −Item [ Disp ] . pAnt = Pos ; ( ∗NAt) ++;
60 p L i s t a −Item [ Disp ] . pProx = −1; ( ∗NAt) ++;
p L i s t a −Item [ Pos ] . pProx = Disp ; ( ∗NAt ) ++;
p L i s t a −pUltimo = Disp ; ( ∗NAt) ++;
return 1 ;
}
65 ( ∗NComp) ++;
p L i s t a −Item [ Disp ] . pAnt = Pos ; ( ∗NAt) ++;
p L i s t a −Item [ Disp ] . pProx = p L i s t a −Item [ Pos ] . pProx ; ( ∗NAt ) ++;
p L i s t a −Item [ Pos ] . pProx = Disp ; ( ∗NAt) ++;
Pos = p L i s t a −Item [ Disp ] . pProx ; ( ∗NAt) ++;
70 p L i s t a −Item [ Pos ] . pAnt = Disp ; ( ∗NAt) ++;
}
void LRPrimeiro ( T L i s t a ∗ p L i s t a , TItem ∗ pItem , double∗ NAt , double∗ NComp)
{
Apontador ProxTmp ;
75 if ( p L i s t a −tamanho == 0 )
return;
( ∗NComp) ++;
∗pItem = p L i s t a −Item [ p L i s t a −p P r i m e i r o ] . Item ;
ProxTmp = p L i s t a −Item [ p L i s t a −p P r i m e i r o ] . pProx ;
80 p L i s t a −Item [ p L i s t a −p P r i m e i r o ] . pProx = p L i s t a −T C e l u l a D i s p ;
p L i s t a −T C e l u l a D i s p = p L i s t a −p P r i m e i r o ;
p L i s t a −p P r i m e i r o = ProxTmp ; ( ∗NAt ) ++;
if( p L i s t a −p P r i m e i r o p L i s t a −n )
p L i s t a −Item [ p L i s t a −p P r i m e i r o ] . pAnt = −1;
85 p L i s t a −tamanho−−; ( ∗NAt) ++;
}
void LRUltimo ( T L i s t a ∗ p L i s t a , TItem ∗ pItem , double∗ NAt , double∗ NComp)
{
Apontador AntTmp ;
90 if ( p L i s t a −tamanho == 0 )
return;
( ∗NComp) ++;
∗pItem = p L i s t a −Item [ p L i s t a −pUltimo ] . Item ;
15
20. AntTmp = p L i s t a −Item [ p L i s t a −pUltimo ] . pAnt ;
95 p L i s t a −Item [ p L i s t a −pUltimo ] . pProx = p L i s t a −T C e l u l a D i s p ;
p L i s t a −T C e l u l a D i s p = p L i s t a −pUltimo ;
p L i s t a −pUltimo = AntTmp ; ( ∗NAt) ++;
if ( ( unsigned int) p L i s t a −pUltimo p L i s t a −n )
p L i s t a −Item [ p L i s t a −pUltimo ] . pProx = −1; ( ∗NAt ) ++;
100 p L i s t a −tamanho−−; ( ∗NAt) ++;
}
Programa 14: Implementações do TLista.c
2.1.13 BubbleSort
Esse método tem um altíssimo custo quando utilizado para ordenar vetores na
forma invertida que é O(n2).
Agora, como o próprio nome sugere, esse método vai borbulhandopelo vetor até
que os elementos estejam ordenados. Neste algoritmo ele compara uma determinada
posição com a anterior, caso a anterior seja maior, ele troca as posição de modo que
o vetor seja ordenado.
// BubbleSort
void B u b b l e S o r t ( TArray ∗ pA , double∗ NAt , double∗ NComp)
{
int i , j ;
5 TItem aux ;
for( i =0; i pA−S i z e −1; i ++)
{
for( j =1; j pA−S i z e −i ; j ++)
{
10 ( ∗NComp) ++;
if (pA−P o s i t i o n s [ j ] . keypA−P o s i t i o n s [ j −1 ] . key )
{
aux = pA−P o s i t i o n s [ j ] ; ( ∗NAt ) ++;
pA−P o s i t i o n s [ j ]=pA−P o s i t i o n s [ j −1 ] ; ( ∗NAt) ++;
15 pA−P o s i t i o n s [ j −1]=aux ; ( ∗NAt ) ++;
}
}
}
}
Programa 15: BubbleSort
2.1.14 BubbleSort com Troca
Uma maneira plausível de otimizar o método de ordenação BubbleSort é criar
uma variável para receber 0 ou 1, onde 1 signica que foi realizado uma troca e
0 que não foi realizado nenhuma troca durante o loop indicando que o vetor está
ordenado, assim evita percorrer o todo vetor quando o mesmo já está ordenado.
// BubbleSort com Troca
void BubbleSortT ( TArray ∗ pA , double∗ NAt , double∗ NComp)
{
int i , j , t r o c a ;
5 TItem aux ;
for( i =0; i pA−S i z e −1; i++ )
{
16
21. t r o c a =0; ( ∗NAt ) ++;
for( j =1; j pA−S i z e −i ; j ++)
10 {
( ∗NComp) ++;
if(pA−P o s i t i o n s [ j ] . keypA−P o s i t i o n s [ j −1 ] . key )
{
aux=pA−P o s i t i o n s [ j ] ;
15 pA−P o s i t i o n s [ j ]=pA−P o s i t i o n s [ j −1 ] ; ( ∗NAt ) ++;
pA−P o s i t i o n s [ j −1]=aux ; ( ∗NAt ) ++;
t r o c a =1; ( ∗NAt) ++;
}
}
20 if ( t r o c a == 0 )
{
( ∗NComp) ++;
break;
}
25 }
}
Programa 16: BubbleSort-T
17
22. 3 Grácos e Tabelas
Abaixo os grácos e tabelas de cada método de ordenação divididas em Atribuições,
Comparações e Tempo de Execução:
3.1 Função QuickSort
3.1.1 Atribuições
Realiza uma quantidade de atribuições bastante interessante exceto no modo
random que obteve aproximadamente 12,4 milhões de comparações.
Gráco e Tabela de Atribuições, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de atribuições realizadas para ordená-los.
Figura 1: Atribuições
18
23. 3.1.2 Comparações
Nota-se pelo gráco e pelas informações contidas na tabela que esse método re-
aliza bastantes comparações, mas mesmo assim, veremos que é um método bastante
eciente de ordenação devido ao tempo de execução.
Gráco e Tabela de Comparações, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de comparações realizadas para ordená-los.
Figura 2: Comparações
3.1.3 Tempo de Execução
Esse método de ordenação tem um excelente resultado sobre o tempo de execução
do algoritmo o que prova o motivo pelo qual é um dos mais utilizado atualmente,
demonstrando, portanto, sua eciência em resolver esse tipo de problema.
Gráco e Tabela do Tempo de Execução, onde abaixo do gráco tem a quantidade
de elementos bem como o tempo de execução para realizado para ordená-los.
19
24. Figura 3: Tempo de Execução
3.2 QuickSort Otimizado
3.2.1 Atribuições
Quando levado em consideração o número de atribuições não houve uma difer-
ença signicativa, para perceber isso basta analisar os grácos e veremos o mesmo
continua praticamente estável, mas é claro com algumas distinções.
Gráco e Tabela de Atribuições, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de atribuições realizadas para ordená-los.
20
25. Figura 4: Atribuições
3.2.2 Comparações
Para o número de comparações verica-se que se tornou praticamente reta quando
observado cada quantidade de elementos separadamente, demonstrando que o número
de comparações nos diferentes modos cresce proporcionalmente de acordo com a
quantidade de elementos.
Gráco e Tabela de Comparações, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de comparações realizadas para ordená-los.
Figura 5: Comparações
21
26. 3.2.3 Tempo de Execução
Ainda obtivemos um resultado impressionante nesse método otimizado, levando
um menor tempo de execução do algoritmo quando comparado com o método nor-
mal, exceto no modem random com uma quantidade de elementos inferior 1.000.000(um
milhão) de elementos.
Gráco e Tabela do Tempo de Execução, onde abaixo do gráco tem a quantidade
de elementos bem como o tempo de execução para realizado para ordená-los.
Figura 6: Tempo de Execução
22
27. 3.3 HeapSort
3.3.1 Atribuições
Para o número de atribuições no HeapSort, permanece praticamente o mesmo
quando comparado com o HeapSort Otimizado.
Gráco e Tabela de Atribuições, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de atribuições realizadas para ordená-los.
Figura 7: Atribuições
23
28. 3.3.2 Comparações
Para o número de comparações no HeapSort, também permanece praticamente
o mesmo quando comparado com o HeapSort Otimizado.
Gráco e Tabela de Comparações, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de comparações realizadas para ordená-los.
Figura 8: Comparações
3.3.3 Tempo de Execução
É impressionante o tempo que o HeapSort levou para ordenar os 1.000.000(um
milhão) de vetores, o que demonstra que esse método é muito eciente para resolução
desse tipo de problema quando a quantidade de elementos é maior.
Gráco e Tabela do Tempo de Execução, onde abaixo do gráco tem a quantidade
de elementos bem como o tempo de execução para realizado para ordená-los.
24
29. Figura 9: Tempo de Execução
3.4 HeapSort Otimizado
3.4.1 Atribuições
Gráco e Tabela de Atribuições, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de atribuições realizadas para ordená-los.
Figura 10: Atribuições
3.4.2 Comparações
Gráco e Tabela de Comparações, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de comparações realizadas para ordená-los.
25
30. Figura 11: Comparações
3.4.3 Tempo de Execução
Quando levado em consideração o tempo de execução verica-se que realmente houve
uma melhora no HeapSort Otimizado, ou seja, se gasta um tempo menor para a
resolução do problema, entretanto não é tão signicativa.
Gráco e Tabela do Tempo de Execução, onde abaixo do gráco tem a quantidade
de elementos bem como o tempo de execução para realizado para ordená-los.
Figura 12: Tempo de Execução
26
31. 3.5 MergeSort
3.5.1 Atribuições
Esse método realiza independentemente da quantidade de elementos no vetor o
mesmo número de atribuições o que demonstra que para a análise do número de
atribuições, a quantidade de elementos não é signicativa, isto é, não depende da
quantidade de elementos pois será a mesma.
Gráco e Tabela de Atribuições, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de atribuições realizadas para ordená-los.
Figura 13: Atribuições
27
32. 3.5.2 Comparações
Quando levado em consideração o número de comparações, então a quantidade
de elementos deve sim ser levada em consideração, uma vez que varia de acordo com
o número de elementos.
Gráco e Tabela de Comparações, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de comparações realizadas para ordená-los.
Figura 14: Comparações
3.5.3 Tempo de Execução
Com relação ao tempo de execução, esse é um método interessante se seu usar
como podemos observar no gráco.
Gráco e Tabela do Tempo de Execução, onde abaixo do gráco tem a quantidade
de elementos bem como o tempo de execução para realizado para ordená-los.
28
33. Figura 15: Tempo de Execução
3.6 MergeSort Otimizado
3.6.1 Atribuições
Nesse método MergeSort Otimizado obtemos uma melhora no número de atribuições
quando comparado ao MergSort, mas ainda sim continua o mesmo número de
atribuições independentemente do número de elementos.
Gráco e Tabela de Atribuições, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de atribuições realizadas para ordená-los.
Figura 16: Atribuições
29
34. 3.6.2 Comparações
Para o Método MergeSort Otimizado com relação ao número de comparações,
não obtivemos uma melhora signicativa, observando-se, portando, que o gráco
continua praticamente estável.
Gráco e Tabela de Comparações, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de comparações realizadas para ordená-los.
Figura 17: Comparações
3.6.3 Tempo de Execução
Com relação ao tempo de execução nota-se, pelo gráco e pelas análises realizado
uma melhora signicativa, uma vez que por exemplo, para ordenar 1.000.000(um
milhão) de vetores no modo normal, gastou-se aproximadamente 37,2 segundos e
no método otimizado aproximadamente 0.56 segundo, o que demonstra uma ótima
melhora e bastante signicativa com relação ao tempo de execução desse algoritmo.
Gráco e Tabela do Tempo de Execução, onde abaixo do gráco tem a quantidade
de elementos bem como o tempo de execução para realizado para ordená-los.
30
35. Figura 18: Tempo de Execução
3.7 SelectSort
3.7.1 Atribuições
O número de atribuições independe da quantidade de elementos, por isso veri-
camos o gráco como sendo uma única linha, onde os resultados são os mesmos, e
mantendo constate para cada quantidade denida de elementos.
Gráco e Tabela de Atribuições, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de atribuições realizadas para ordená-los.
31
36. Figura 19: Atribuições
3.7.2 Comparações
O número de comparações desse método cresce proporcionalmente de acordo
com a quantidade de elementos analisados, mantendo constate para cada quantidade
denida de elementos.
Gráco e Tabela de Comparações, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de comparações realizadas para ordená-los.
Figura 20: Comparações
32
37. 3.7.3 Tempo de Execução
Com relação ao tempo de execução, esse não é um método ideal para se utilizar
para elementos superiores a 1.000(mil) uma vez que há um acréscimo bastante sig-
nicativo no tempo de execução do algoritmo o que demonstra ser não viável a sua
utilização pra essa nalidade.
Gráco e Tabela do Tempo de Execução, onde abaixo do gráco tem a quantidade
de elementos bem como o tempo de execução para realizado para ordená-los.
Figura 21: Tempo de Execução
33
38. 3.8 SelectSort Otimizado
3.8.1 Atribuições
Para atribuições houve uma melhora signicativa quando se utiliza o método
otimizado, exceto pelo modo random que obteve uma pequena diferença. Ainda,
podemos observar que não houve nenhuma atribuição quando o vetor estiver orde-
nado, o que não acontecia no método normal.
Gráco e Tabela de Atribuições, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de atribuições realizadas para ordená-los.
Figura 22: Atribuições
34
39. 3.8.2 Comparações
Para o número de comparações não houve resultados signicativos, uma vez que
continuou praticamente o mesmo, mas é claro, usou-se mais comparações, como
podemos observar no gráco abaixo.
Gráco e Tabela de Comparações, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de comparações realizadas para ordená-los.
Figura 23: Comparações
3.8.3 Tempo de Execução
Sobre o tempo de execução do algoritmo só obteve uma melhora nos modos
sorted(ordenado) e no inverted(invertido), já nos outros, houve um acréscimo no
tempo, o que não foi conveniente a otimização quando formos pegar um vetor em
modo almost sorted(quase ordenado) ou em modo random(aleatório).
Gráco e Tabela do Tempo de Execução, onde abaixo do gráco tem a quantidade
de elementos bem como o tempo de execução para realizado para ordená-los.
35
40. Figura 24: Tempo de Execução
3.9 InsertSort
3.9.1 Atribuições
Esse método realiza muitas atribuições como podemos observar no gráco e na
tabela, o que não pode ser um método muito eciente quando levado em consideração
o número de atribuições.
Gráco e Tabela de Atribuições, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de atribuições realizadas para ordená-los.
Figura 25: Atribuições
36
41. 3.9.2 Comparações
Para comparações, ainda sim realiza muitas comparações quando vericado no
gráco, exceto quando o vetor estiver ordenado, pois dessa maneira não realiza
nenhuma comparação.
Gráco e Tabela de Comparações, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de comparações realizadas para ordená-los.
Figura 26: Comparações
3.9.3 Tempo de Execução
Ainda sim leva um tempo considerável para ordenar muitos elementos, o que,
dependendo da quantidade de elementos, não seria recomendável utilizar esse método
de ordenação.
Gráco e Tabela do Tempo de Execução, onde abaixo do gráco tem a quantidade
de elementos bem como o tempo de execução para realizado para ordená-los.
37
42. Figura 27: Tempo de Execução
3.10 InsertSort com o elemento Sentinela
3.10.1 Atribuições
Devido o elemento sentinela, fazemos ainda mais atribuições quando comparado
ao método sem o sentinela. Ainda sim não houve uma diferença signicativa pois o
gráco continua estável.
Gráco e Tabela de Atribuições, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de atribuições realizadas para ordená-los.
Figura 28: Atribuições
38
43. 3.10.2 Comparações
Para o número de comparações, o resultado é praticamente o mesmo da análise
de atribuições, o gráco continua estável e não houve uma diferença brusca nos
dados.
Gráco e Tabela de Comparações, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de comparações realizadas para ordená-los.
Figura 29: Comparações
3.10.3 Tempo de Execução
Ainda não obtivemos um diferencial tão signicativo com relação ao tempo de
execução desse método com o elemento sentinela, continuando o gráco estável e com
algumas diferenças no tempo, o que varia de acordo com a quantidade de elementos.
Gráco e Tabela do Tempo de Execução, onde abaixo do gráco tem a quantidade
de elementos bem como o tempo de execução para realizado para ordená-los.
39
44. Figura 30: Tempo de Execução
3.11 InsertSort por Cursores
3.11.1 Atribuições
Esse método realiza a mesma quantidade de comparações para todos os métodos,
sendo mais precisamente a mesma igual à quantidade de elementos ordenados.
Gráco e Tabela de Atribuições, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de atribuições realizadas para ordená-los.
40
45. Figura 31: Atribuições
3.11.2 Comparações
Para comparações, ainda sim realiza muitas comparações quando vericado no
gráco, exceto quando o vetor estiver invertido, pois dessa maneira realiza uma
menor quantidade de comparações.
Gráco e Tabela de Comparações, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de comparações realizadas para ordená-los.
Figura 32: Comparações
41
46. 3.11.3 Tempo de Execução
Ainda sim leva um tempo considerável para ordenar muitos elementos, exceto
quando o vetor estiver invertido, o que, dependendo da quantidade de elementos,
não seria recomendável utilizar esse método de ordenação.
Gráco e Tabela do Tempo de Execução, onde abaixo do gráco tem a quantidade
de elementos bem como o tempo de execução para realizado para ordená-los.
Figura 33: Tempo de Execução
42
47. 3.12 BubbleSort
3.12.1 Atribuições
Para o BubbleSort, verica-se que esse método realiza o mesmo número de com-
parações independentemente da forma com que os elementos estão ordenados no
vetor, portando as linhas do gráco se coincidem como vemos no gráco de com-
parações.
Gráco e Tabela de Atribuições, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de atribuições realizadas para ordená-los.
Figura 34: Atribuições
43
48. 3.12.2 Comparações
Quando levado em consideração o número de atribuições, párea cada caso tere-
mos valores distintos utilizando o método BubbleSort como é vericado no gráco.
Ainda, para quando o vetor estiver ordenado, fazemos 0 atribuições.
Gráco e Tabela de Comparações, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de comparações realizadas para ordená-los.
Figura 35: Comparações
3.12.3 Tempo de Execução
Para uma grande quantidade de elementos esse não é um método adequado para
ordenar vetores, uma vez que para ordenar 100.000(cem mil) vetores requer muito
tempo para realizar a tarefa, mas para números pequenos é adequado.
Gráco e Tabela do Tempo de Execução, onde abaixo do gráco tem a quantidade
de elementos bem como o tempo de execução para realizado para ordená-los.
44
49. Figura 36: Tempo de Execução
3.13 BubbleSort com Troca
3.13.1 Atribuições
Para atribuições, verica-se que não houve uma melhora signicativa, pois os
grácos de com e sem troca são bem parecidos e os dados são bem próximos, portanto
se for levado em consideração o número de atribuições não fará muita diferença em
utilizar o método com ou sem troca.
Gráco e Tabela de Atribuições, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de atribuições realizadas para ordená-los.
45
50. Figura 37: Atribuições
3.13.2 Comparações
Devido a vericação no loop se houve ou não troca, verica-se que esse método
é mais eciente do que o BubbleSort convencional, então, o método com elemento
troca é mais eciente. Assim, quando comparado em números de comparações,
vericamos pelo gráco que esse método faz menos comparações do que o método
sem a troca.
Gráco e Tabela de Comparações, onde abaixo do gráco tem a quantidade de
elementos bem como a quantidade de comparações realizadas para ordená-los.
Figura 38: Comparações
46
51. 3.13.3 Tempo de Execução
Sobre o tempo de execução, verica-se que houve uma melhora signicativa com
relação ao método sem troca, exceto para o modo random, entretanto, ainda é viável
utilizar o método com troca, pois como podemos observar pelo gráco, esse método
requer menos tempo para a resolução do problema proposto.
Gráco e Tabela do Tempo de Execução, onde abaixo do gráco tem a quantidade
de elementos bem como o tempo de execução para realizado para ordená-los.
Figura 39: Tempo de Execução
47
52. 4 Análise de complexidade dos algoritmos
Levado em consideração o número de comparações.
4.1 Sort.h
4.1.1 Função QuickSort
No pior caso tem ordem de complexidade O(n2) quando o pivô selecionado for o
maior elemento do vetor ou caso ele esteja no extremo do vetor.
4.1.2 HeapSort
No pior, tanto para qualquer, caso tem ordem de complexidade (n.lg(n)).
4.1.3 MergeSort
No pior, tanto para qualquer, caso tem ordem de complexidade (n.lg(n)).
4.1.4 SelectSort
Decido aos dois loops, um i partindo de 0 até pA-Size-1 e o outro j partindo
de i+1 indo até pA-Size. Possui ordem de complexidade O(n2).
f(n) =
n−2
i=0
(n − i − 1) = (n2
− n)/2 (1)
4.1.5 InsertSort
No pior caso, o número de comparações é C(n) = (2+1 + 2+2 + ... + 2+n-1)
= (n2+3n-4)/2, portanto possui ordem de complexidade O(n2).
4.1.6 BubbleSort
Devido aos dois loops, um i partindo de 0 até pA-Size-1 e o outro j partindo
de 1 indo até pA-Size-i. Possui ordem de complexidade O(n2).
f(n) =
n−2
i=0
(n − i − 1) = (n2
− n)/2 (2)
48
53. 5 Testes
Teste para vericar se os vetores foram corretamente ordenados:
Figura 40: Teste de Ordenação
49
55. 6 Conclusão
Verica-se que para cada situação e o modo com que o vetor está ordenado,
bem como a quantidade de elementos, cada método é muito útil para a resolução
de problemas de ordenação, demonstrando que para cada caso é viável utilizar um
método especíco de ordenação. Ainda pude aprender a analisar os algoritmos de
forma a juntar dados sobre ele, isto é, coletar informações importantes sobre o seu
funcionamento e armazenar em gráco e tabela de forma que seja mais interativa
a avaliação para que qualquer pessoa com o mínimo de relacionamento na área da
computação possa entender, pelo menos, e identicar qual é o melhor método em
determinada situação, assim facilitando o seu trabalho na explicação desses proble-
mas a uma determinada pessoa e é claro, obtive mais maturidade nos métodos de
ordenação bem como a melhor compreensão sobre esses tipos de problemas.
Referências
[1] David Menotti Algoritmos e Estruturas de Dados I: Ordenação I SelectSort,
InsertSort, BubbleSort. http://www.decom.ufop.br/prof/menotti/aedI092/
slides/aula14-Ordenacao.ppt, visitado em 14/11/2009.
[2] David Menotti Algoritmos e Estruturas de Dados I: Ordenação III
QuickSort. http://www.decom.ufop.br/prof/menotti/aedI092/slides/
aula16-QuickSort.ppt, visitado em 14/11/2009.
[3] David Menotti Algoritmos e Estruturas de Dados I: Ordenação
IV HeapSort. http://www.decom.ufop.br/prof/menotti/aedI092/slides/
aula17-HeapSort.ppt, visitado em 14/11/2009.
[4] David Menotti Algoritmos e Estruturas de Dados I: Ordenação V
MergeSort. http://www.decom.ufop.br/prof/menotti/aedI092/slides/
aula18-MergeSort.ppt, visitado em 14/11/2009.
[5] David Menotti Algoritmos e Estruturas de Dados I: Filas. http://
www.decom.ufop.br/prof/menotti/aedI092/slides/aula12-Fila.ppt, visi-
tado em 14/11/2009.
51