







Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Encontra documentos específicos para os exames da tua universidade
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Estruturas de Dados Avançadas - atividade
Tipologia: Notas de estudo
1 / 13
Esta página não é visível na pré-visualização
Não perca as partes importantes!








Trabalho de Avalia¸c˜ao
O algoritmo foi modificado de modo que quando o procedimento QuickSort for chamado em um subarranjo com menos de k elementos, executa a ordena¸c˜ao por inser¸c˜ao sobre o arranjo inteiro, a fim de concluir o processo de ordena¸c˜ao. Segundo Thomas H. Cormen no seu livro ”Introduction to Algorithms - Second Edition”, este algoritmo misto ´e executado no tempo esperado O(nk + n log(n/k)). Abaixo segue o algoritmo Quick Sort modificado implementado em Linguagem C
Listing 1: QuickSortMod.c
// Quick Sort Modificado // utiliza um outro m´etodo de ordena¸c~ao simples quando // as cole¸c~oes ficam menores
void imprimir_lista () ;
typedef struct { int chave ; } TItem ;
TItem lista [ MaxTam ];
void iniciar_lista () { // Inicializar o gerador de n´umeros aleat´orios // Com time ( NULL ) srand ( time ( NULL ) ) ; int i ; for ( i = 0; i < MaxTam ; i ++) { lista [ i ]. chave = rand () % MaxRand ; } }
void preencher_lista () { int i ; for ( i = 0; i < MaxTam ; i ++) { printf ( " \ n % d % c elemento : " ,i +1 ,167) ; scanf ( " % d " ,& lista [ i ]. chave ) ; }
void quicksort ( int p , int r ) { int q ; if ( p < r ) { q = particao (p , r ) ; // printf (" p : %d , q : %d , r : % d " ,p ,q , r ) ; quicksort (p , q ) ; quicksort ( q +1 , r ) ; }
if ( fabs (r - p ) < Max ) InsertionSort (r - p +1) ; return ; }
void imprimir_lista () { printf ( " ----- Lista - - - - -\ n " ) ; int i ; for ( i = 0; i < MaxTam ; i ++) printf ( " lista [%5 d ] = %5 d \ n " , i + 1 , lista [ i ]. chave ) ; printf ( " - - - - - - - - - - - - - - - - -\ n " ) ; }
void imprime_tempo ( clock_t tini , clock_t tfim ) { printf ( " Tempo = %2.5 f segundos \ n " , (( double ) ( tfim - tini ) / (( double ) CLOCKS_PER_SEC ) ) ) ; }
main () { clock_t tini , tfim ;
iniciar_lista () ; // preencher_lista () ; // imprimir_lista () ; tini = clock () ; quicksort (0 , MaxTam -1) ; tfim = clock () ; // imprimir_lista () ;
imprime_tempo ( tini , tfim ) ;
// Sequencia de comandos equivalentes ao system (" pause ") ; getchar () ; scanf ( " c \ n " ) ; }
Selection Sort
Um dos algoritmos de ordena¸c˜ao mais simples cujo princ´ıpio de funcionamento ´e o seguinte: selecione o menor item do vetor e a seguir troque-o com o item que est´a na primeira posi¸c˜ao do vetor. Repita estas duas opera¸c˜oes com os n - 1 itens restantes, depois com os n - 2 itens, at´e que reste apenas um elemento.
i: 1 2 3 4 5 Chaves iniciais: 5 4 2 8 3 i = 2 2 4 5 8 3 i = 3 2 3 5 8 4 i = 4 2 3 4 8 5 i = 5 2 3 4 5 8
obs: as chaves em negrito sofreram uma troca entre si.
C(n) = n
2 2 −^
n 2 M(n) = 3(n − 1)
O m´etodo Selection Sort n˜ao ´e est´avel.
Insertion Sort
Em cada passo, a partir do i = 2, o i-´esimo item da sequˆencia fonte ´e apanhado e transferido para a sequˆencia destino, sendo inserido no seu lugar apropriado.
i: 1 2 3 4 5 Chaves iniciais: 5 4 2 8 3 i = 2 4 5 2 8 3 i = 3 2 4 5 8 3 i = 4 2 4 5 8 3 i = 5 2 3 4 5 8
Quick Sort
Neste algoritmo de ordena¸c˜ao o vetor ´e particionado em dois por meio de um procedimento recursivo. Essa divis˜ao ocorre at´e que o vetor fique com apenas um elemento, enquanto os demais ficam ordenados `a medida que ocorre o particionamento.
Este comportamento pode ser descrito pelo seguinte algoritmo:
i: 0 1 2 3 4 Chaves iniciais: 5 4 2 8 3
Melhor caso: C(n) = n log n − n + 1 Caso m´edio: C(n) ≈ 1 , 386 n log n − 0 , 846 n
O m´etodo QuickSort n˜ao ´e est´avel.
Heap Sort
Este algoritmo de ordena¸c˜ao ´e baseado na estrutura de dados Heap, que ´e definido como uma sequˆencia de itens com chaves. Esta sequˆencia de itens pode ser vista como uma ´arvore bin´aria onde cada n´o possui no m´aximo 2 filhos. Cada v´ertice da ´arvore corresponde a um elemento do vetor. Pode-se garantir que a ´arvore ´e completamente preenchida exceto no ´ultimo n´ıvel, onde pode ou n˜ao ser completamente preenchida. Cada n´ıvel ´e sempre preenchido da esquerda para a direita. Na representa¸c˜ao do Heap em um arranjo, a maior chave est´a sempre na posi¸c˜ao 1 do vetor. A partir do Heap obtido, pega-se o item na posi¸c˜ao 1 do vetor(raiz do Heap) e troca-se com o item que est´a na posi¸c˜ao n do vetor. A seguir, basta usar o procedimento ordenar para reconstituir o Heap para os itens A[1], A[2], ...A[n - 1]. Repita estas duas opera¸c˜oes com os n
Vetor analisado e sua representa¸c˜ao em ´arvore 1 2 3 4 5 5 4 2 8 3
Constru¸c˜ao do Heap Chaves iniciais: 5 4 2 8 3 i = 2: 5 4 2 8 3 5 8 2 4 3 i = 1: 5 8 2 4 3 8 5 2 4 3 8 5 2 4 3 8 5 2 4 3
Ordena¸c˜ao usando HeapSort i = 5 8 5 2 4 3 3 5 2 4 8 3 5 2 4 8 5 3 2 4 8 5 3 2 4 8 5 4 2 3 8 i = 4 5 4 2 3 3 4 2 5 3 4 2 5 4 3 2 5 i = 3 4 3 2 2 3 4 2 3 4 3 2 4 i = 2 3 2 2 3 2 3 4 5 8
Qualquer entrada: C(n) = O(n log n)
de elementos cada vez, aumentando o tamanho das listas a serem ordenadas a cada ciclo de teste
Tamanho da lista 1000 10000 100000 SelectionSort 0.00400 seg. 0.32700 seg. 31.79900 seg. InsertionSort 0.00400 seg. 0.31000 seg. 23.08600 seg. ShellSort 0.00000 seg. 0.00400 seg. 0.09300 seg. QuickSort 0.00000 seg. 0.00400 seg. 0.03900 seg. HeapSort 0.00100 seg. 0.00600 seg. 0.16700 seg. BubbleSort 0.01200 seg. 1.11400 seg. 110.02600 seg.
Concluimos que o met´odo de ordena¸c˜ao que obteve melhor tempo em geral foi o QuickSort, seguido dos outros m´etodos eficientes testados ShellSort e HeapSort. Os conhecidos m´etodos de ordena¸c˜ao simples (SelectionSort, InsertionSort e BubbleSort) tiveram em seus respectivos tempos de execu¸c˜ao um crscimento significativo para a maior entrada testada, logo percebemos um crescimento exponencial que confirma a an´alise de complexidade algoritma destes de custo O(n^2 ), tendo o BubbleSort os piores tempos obtidos.
Neste algoritmo de ordena¸c˜ao, o vetor ´e dividido em vetores com a metade do tamanho original por meio de um procedimento recursivo. Essa divis˜ao ocorre at´e que o vetor fique com um elemento e estes sejam ordenados intercalados. Neste algoritmo, ´e aplicada a t´ecnica de divis˜ao e conquista, uma t´ecnica recursiva que envolve trˆes passos em cada n´ıvel da recurs˜ao:
Listing 2: MergeSort.c
for ( i = inicio_vetor2 ;i <= fim ; i ++) { aux [ poslivre ] = lista [ i ]; poslivre = poslivre + 1; }
for ( i = inicio ;i <= fim ; i ++) { lista [ i ] = aux [ i ]; } }
void mergesort ( int inicio , int fim ) { int meio ; if ( inicio < fim ) { meio = ( inicio + fim ) /2; mergesort ( inicio , meio ) ; mergesort ( meio +1 , fim ) ; intercala ( inicio , fim , meio ) ; } }
void imprimir_lista () { printf ( " ----- Lista - - - - -\ n " ) ; int i ; for ( i = 0; i < MaxTam ; i ++) printf ( " lista [%5 d ] = %5 d \ n " , i + 1 , lista [ i ]. chave ) ; printf ( " - - - - - - - - - - - - - - - - -\ n " ) ; }
void imprime_tempo ( clock_t tini , clock_t tfim ) { printf ( " Tempo = %2.5 f segundos \ n " , (( double ) ( tfim - tini ) / (( double ) CLOCKS_PER_SEC ) ) ) ; }
main () { clock_t tini , tfim ;
iniciar_lista () ; // preencher_lista () ; // imprimir_lista () ; tini = clock () ; mergesort (0 , MaxTam - 1) ; tfim = clock () ; // imprimir_lista () ;
imprime_tempo ( tini , tfim ) ;
// Sequencia de comandos equivalentes ao system (" pause ") ; getchar () ; scanf ( " c \ n " ) ; }