Estruturas de Dados 2 Técnicas de Projeto de Algoritmos Dividir e Conquistar IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 1/83
Projeto de Algoritmos por Divisão e Conquista Introdução Busca Recursiva Ordenação: InsertionSort, MergeSort, HeapSort e QuickSort Resumo IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 2/83
Introdução Dividir e Conquistar é uma técnica de projeto de algoritmos que consiste em resolver um problema a partir da solução de sub-problemas menores do mesmo tipo. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 3/83
Introdução Dividir e Conquistar é uma técnica de projeto de algoritmos que consiste em resolver um problema a partir da solução de sub-problemas menores do mesmo tipo. Se os sub-problemas obtidos após a divisão ainda são muito grandes para a solução direta, aplica-se novamente a divisão, até ter problemas pequenos o suficiente para terem solução trivial ou direta. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 4/83
Introdução Após o processo de divisão em sub-problemas menores, e sua conquista, basta combinar os resultados dos sub-problemas menores, para obter a solução para o problema como um todo. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 5/83
Passos para divisão e conquista : 1. Divisão: propor uma forma de dividir o problema original em sub-problemas iguais, porém menores (recursivamente); 2. Conquista: ao se obter sub-problemas pequenos o suficiente, resolvê-los diretamente; 3. Combinação: combinar as soluções de forma a obter a solução ao problema original. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 6/83
Vantagens Solução direta do ponto de vista da recursividade; Elegância; Usualmente produz algoritmos eficientes (complexidade logarítmica!!!) Desvantagem Recursão!!!! IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 7/83
Como aplicar? Processo Indutivo ao projeto de algoritmos(recursão) Aplicável sempre que for possível obter subproblemas menores independentes entre si Procurar uma divisão igualitária de um problema em diversos sub-problemas... Deve ser possível (e de preferência simples e rápido) combinar os resultados dos sub-problemas... IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 8/83
Justificativa Esta técnica pode ser empregada em diversas situações comuns porém importantes: Somar N números; Encontrar um elemento em um vetor ordenado; IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 9/83
Exemplo da aplicação da técnica: Como somar N números, a 1, a 2,..., a n? Se n é 1, a soma é o próprio a 1. Se n>1, podemos dividir o problema em dois subproblemas menores: 1.Somar os números de a 1 até a n/2 ; 2.Somar os número de a n/2 até a n ; 3.Somar os resultados!!! IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 10/83
Exemplo da aplicação da técnica: Como somar N números, a 1, a 2,..., a n? Eficiência???? IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 11/83
Exemplo da aplicação da técnica: Como somar N números, a 1, a 2,..., a n? Eficiência???? O(n)...(Melhor que uma abordagem exaustiva????) IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 12/83
Exemplo da aplicação da técnica: Como somar N números, a 1, a 2,..., a n? Eficiência???? O(n)...(Melhor que uma abordagem exaustiva????) Claramente NÃO!!!! IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 13/83
Exemplo da aplicação da técnica: Como somar N números, a 1, a 2,..., a n? Eficiência???? O(n)...(Melhor que uma abordagem exaustiva????) Claramente NÃO!!!! Portanto, aplicar Divisão e Conquista não garante, por si só, a obtenção de algoritmos eficientes! IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 14/83
OUTRO exemplo: Buscar um elemento! Como encontrar o elemento em um vetor de tamanho N: a 1, a 2,..., a n? Se n é 1, e o elemento a 1 é o procurado, achou, senão não achou! Se n>1, podemos dividir o problema em dois subproblemas menores: 1.Encontrar o elemento no vetor de a 1 até a n/2 2.Encontrar o elemento no vetor de a n/2 até a n IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 15/83
Mas esta técnica não consegue gerar resultados melhores que a Força Bruta??? IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 16/83
Mas esta técnica não consegue gerar resultados melhores que a Força Bruta??? Pode sim... IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 17/83
Mas esta técnica não consegue gerar resultados melhores que a Força Bruta??? Pode sim... Basta aplicá-la adequadamente...! IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 18/83
Mas esta técnica não consegue gerar resultados melhores que a Força Bruta??? Pode sim... Basta aplicá-la adequadamente...! Exemplo de uso adequado: Busca Binária. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 19/83
Busca Binária: Dividir e Conquistar Encontrar um determinado elemento (chave) em um vetor ordenado de tamanho N: a 1, a 2,..., a n?: Verificar se a chave está na posição a x = a n/2 : Se estiver, encontrou! Se não estiver, realizar a busca binária nos vetores: a 1 até a x-1,se chave < a x, ou em a x+1 até a n se chave > a x. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 20/83
Busca Binária: Exemplo: Encontrar o número 12 na lista: 3 5 7 8 9 11 12 19 IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 21/83
Busca Binária: Exemplo: Encontrar o número 12 na lista: 3 5 7 8 9 11 12 19 3 5 7 8 9 11 12 19 (está na posição X=n/2?)Ñ! IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 22/83
Busca Binária: Exemplo: Encontrar o número 12 na lista: 3 5 7 8 9 11 12 19 3 5 7 8 9 11 12 19 (está na posição X=n/2?)Ñ! 3 5 7 8 9 11 12 19 (está na posição X=n/2?)S! IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 23/83
Busca Binária: Tá, mas e daí???? Dividir e Conquistar Bem, a eficiência deste algoritmo é Θ(lg n)... Muito mais eficiente que a abordagem Força Bruta......pena que o vetor precisa estar ordenado......mas podemos aplicar a técnica de Divisão e Conquista para ordenar vetores também!!!!! IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 24/83
Ordenação com Divisão e Conquista: Problema: Ordenar um vetor de tamanho N: a 1, a 2,..., a n Um vetor de um elemento já está ordenado! Um vetor de tamanho n pode ser ordenado pela intercalação de dois sub-vetores: 1.Um vetor de a 1 até a n/2 2.Outro vetor de a n/2 até a n IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 25/83
Ordenação com Divisão e Conquista: Problema: Ordenar um vetor de tamanho N: a 1, a 2,..., a n Um vetor de um elemento já está ordenado! Um vetor de tamanho n pode ser ordenado pela intercalação de dois sub-vetores: 1.Um vetor de a 1 até a n/2 2.Outro vetor de a n/2 até a n Esta maneira de ordenar dá origem ao algoritmo recursivo de ordenação MergeSort!!! IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 26/83
Ordenação com Divisão e Conquista: Problema: Ordenar um vetor de tamanho N: a 1, a 2,..., a n Um vetor de um elemento já está ordenado! Um vetor de tamanho n pode ser ordenado pela intercalação de dois sub-vetores: 1.Um vetor de a 1 até a n/2 2.Outro vetor de a n/2 até a n Esta maneira de ordenar dá origem ao algoritmo recursivo de ordenação MergeSort!!! Isto é projetar um algoritmo por divisão e conquista!!! IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 27/83
MergeSort: Se a função intercala for eficiente=o(n) Detalhe: para conseguir implementar a intercalação de forma eficiente, é necessário um vetor auxiliar, o que aumenta a memória necessária para o algoritmo...não é uma ordenação in-place,como a Ordenação por Seleção T(n) = 2T(n/2) + O(n) Logo, Mergesort é Θ(n lg n) (Master) IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 28/83
MergeSort(A, e, d): : Pseudo-Código IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 29/83
Intercala(A, e, d): Pseudo-Código IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 30/83
Aplicando Dividir e Conquistar de outra forma: Seja S um conjunto de n 2 inteiros e x um elemento qualquer de S. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 31/83
Aplicando Dividir e Conquistar de outra forma: Seja S um conjunto de n 2 inteiros e x um elemento qualquer de S. Sejam S1 e S2 os subconjuntos de {S x} dos elementos menores ou iguais a x e maiores que x, respectivamente. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 32/83
Aplicando Dividir e Conquistar de outra forma: Seja S um conjunto de n 2 inteiros e x um elemento qualquer de S. Sejam S1 e S2 os subconjuntos de {S x} dos elementos menores ou iguais a x e maiores que x, respectivamente. Ambos S1 e S2 possuem menos de n elementos. Por hipótese de indução, sabemos ordenar os conjuntos S1 e S2. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 33/83
Aplicando Dividir e Conquistar de outra forma: Seja S um conjunto de n 2 inteiros e x um elemento qualquer de S. Sejam S1 e S2 os subconjuntos de {S x} dos elementos menores ou iguais a x e maiores que x, respectivamente. Ambos S1 e S2 possuem menos de n elementos. Por hipótese de indução, sabemos ordenar os conjuntos S1 e S2. Podemos obter S ordenado concatenando S1 ordenado, x e S2 ordenado. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 34/83
Aplicando Dividir e Conquistar de outra forma: Seja S um conjunto de n 2 inteiros e x um elemento qualquer de S. Sejam S1 e S2 os subconjuntos de {S x} dos elementos menores ou iguais a x e maiores que x, respectivamente. Ambos S1 e S2 possuem menos de n elementos. Por hipótese de indução, sabemos ordenar os conjuntos S1 e S2. Podemos obter S ordenado concatenando S1 ordenado, x e S2 ordenado. Esta abordagem dá origem ao algoritmo QuickSort!!! IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 35/83
Em contraste ao Mergesort, no Quicksort é a operação de divisão que é mais custosa: depois de escolhermos o pivô(x), temos que separar os elementos do vetor maiores que o x dos menores ou iguais a x. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 36/83
Em contraste ao Mergesort, no Quicksort é a operação de divisão que é mais custosa: depois de escolhermos o pivô(x), temos que separar os elementos do vetor maiores que o x dos menores ou iguais a x. Conseguimos fazer essa divisão com (n) operações: basta varrer o vetor com dois apontadores, um varrendo da direita para a esquerda e outro da esquerda para a direita, em busca de elementos situados na parte errada do vetor, e trocar um par de elementos de lugar quando encontrado. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 37/83
Em contraste ao Mergesort, no Quicksort é a operação de divisão que é mais custosa: depois de escolhermos o pivô(x), temos que separar os elementos do vetor maiores que o x dos menores ou iguais a x. Conseguimos fazer essa divisão com (n) operações: basta varrer o vetor com dois apontadores, um varrendo da direita para a esquerda e outro da esquerda para a direita, em busca de elementos situados na parte errada do vetor, e trocar um par de elementos de lugar quando encontrado. Após essa etapa basta ordenarmos os dois trechos do vetor recursivamente para obtermos o vetor ordenado, ou seja, a conquista é imediata. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 38/83
Quicksort(A,e,d) - Pseudo-Código: IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 39/83
Quicksort(A,e,d) - Pseudo-Código(cont): IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 40/83
Quicksort- Idéia Base 1. Selecionar um elemento para ser o pivô 2. Rearranjar a lista de modo que todos os elementos nas posições a esquerda do pivô sejam menores ou iguais a ele, e aqueles a direita do pivô sejam maiores que ele. 3. Permutar o pivô com o último elemento da primeira sub-lista(menores ou iguais). Agora o pivô está em sua posição final. 4. Ordenar as duas sub-listas. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 41/83
QuickSort Exemplo 5 3 1 9 8 2 4 7 partition 2 3 1 4 5 8 9 7 2 3 1 4 partition 1 2 3 4 partition 1 3 4 partition 4 8 9 7 partition 7 8 9 7 9 IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 42/83
Quicksort Análise da Complexidade Quantas comparações e quantas trocas o algoritmo Quicksort executa no pior caso? IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 43/83
Quicksort Análise da Complexidade Quantas comparações e quantas trocas o algoritmo Quicksort executa no pior caso? Certamente a operação de divisão tem complexidade (n), mas o tamanho dos dois subproblemas depende do pivô escolhido. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 44/83
Quicksort Análise da Complexidade Quantas comparações e quantas trocas o algoritmo Quicksort executa no pior caso? Certamente a operação de divisão tem complexidade (n), mas o tamanho dos dois subproblemas depende do pivô escolhido. No pior caso, cada divisão sucessiva do Quicksort separa um único elemento dos demais, recaindo na recorrência: T(n) = 0, se n = 1 T(n) = T(n 1) + n, se n > 1, IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 45/83
Quicksort Análise da Complexidade Quantas comparações e quantas trocas o algoritmo Quicksort executa no pior caso? Certamente a operação de divisão tem complexidade (n), mas o tamanho dos dois subproblemas depende do pivô escolhido. No pior caso, cada divisão sucessiva do Quicksort separa um único elemento dos demais, recaindo na recorrência: T(n) = 0, se n = 1 T(n) = T(n 1) + n, se n > 1, Portanto, (n2 ) comparações e trocas são executadas no pior caso!!!!!! IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 46/83
Mas o Quicksort não era o algoritmo de ordenação mais eficiente???? IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 47/83
Mas o Quicksort não era o algoritmo de ordenação mais eficiente???? Então, o algoritmo Quicksort é assintoticamente menos eficiente que o Mergesort no pior caso. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 48/83
Mas o Quicksort não era o algoritmo de ordenação mais eficiente???? Então, o algoritmo Quicksort é assintoticamente menos eficiente que o Mergesort no pior caso. Entretanto, no caso médio, o Quicksort efetua (n log n) comparações e trocas. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 49/83
Mas o Quicksort não era o algoritmo de ordenação mais eficiente???? Então, o algoritmo Quicksort é assintoticamente menos eficiente que o Mergesort no pior caso. Entretanto, no caso médio, o Quicksort efetua (n log n) comparações e trocas. Assim, na prática, o Quicksort é bastante eficiente, com uma vantagem adicional em relação ao Mergesort: é in place, isto é, não utiliza um vetor auxiliar. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 50/83
Considerando que o pior caso não ocorre com freqüência, pois usualmente, pegando um pivô aleatório, é muito difícil escolher sempre um pivô que divida o vetor de tamanho n em dois vetores, um dos menores e outro dos maiores que o pivô, com tamanhos (n-1) e 1... IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 51/83
Considerando que o pior caso não ocorre com freqüência, pois usualmente, pegando um pivô aleatório, é muito difícil escolher sempre um pivô que divida o vetor de tamanho n em dois vetores, um dos menores e outro dos maiores que o pivô, com tamanhos (n-1) e 1... Desta forma, supondo uma divisão do vetor de tamanho n em dois sub-vetores (n/2), e considerando o tempo de separação entre os maiores e os menores que o pivô sendo O(n)... IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 52/83
Considerando que o pior caso não ocorre com freqüência, pois usualmente, pegando um pivô aleatório, é muito difícil escolher sempre um pivô que divida o vetor de tamanho n em dois vetores, um dos menores e outro dos maiores que o pivô, com tamanhos (n-1) e 1... Desta forma, supondo uma divisão do vetor de tamanho n em dois sub-vetores (n/2), e considerando o tempo de separação entre os maiores e os menores que o pivô sendo O(n)... O tempo médio T(n)=2T(n/2)+O(n) = O(n lg n) IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 53/83
Ordenação: Mas não há um algoritmo que seja eficiente em todos os casos, e in place ao mesmo tempo? IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 54/83
Ordenação: Mas não há um algoritmo que seja eficiente em todos os casos, e in place ao mesmo tempo? Vocês tinham que perguntar????? IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 55/83
Ordenação: Mas não há um algoritmo que seja eficiente em todos os casos, e in place ao mesmo tempo? Vocês tinham que perguntar????? Este algoritmo chama-se HeapSort. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 56/83
Ordenação: Mas não há um algoritmo que seja eficiente em todos os casos, e in place ao mesmo tempo? Vocês tinham que perguntar????? Este algoritmo chama-se HeapSort. E é baseado numa estrutura de dados inteligente denominada Heap... implementa uma fila de prioridades... Podermos utilizá-la para fazer uma ordenação inplace e Θ(n lg n)!!!! (Mas o Quicksort ainda é mais rápido!!!!) IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 57/83
Ordenação por Heap(HeapSort): Tarefa: Implementar a estrutura de dados Heap para podermos utilizá-la para fazer uma ordenação in-place e Θ(n lg n)!!!! IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 58/83
Ordenação por Heap(HeapSort): Tarefa: Implementar a estrutura de dados Heap para podermos utilizá-la para fazer uma ordenação in-place e Θ(n lg n)!!!! Mas o que é um Heap??? IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 59/83
Ordenação por Heap(HeapSort): Tarefa: Implementar a estrutura de dados Heap para podermos utilizá-la para fazer uma ordenação in-place e Θ(n lg n)!!!! Mas o que é um Heap??? É uma simulação de uma árvore binária completa utilizando um vetor!!!! IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 60/83
Heap: Vetor que apresenta as seguintes características: Vetor A de tamanho N (lenght(a) = nº de nodos da árvore) A[1] = raiz da árvore binária (primeira posição do vetor) Para calcular a posição de qualquer nodo, utilizamos as funções PARENT, LEFT E RIGHT: PARENT(i) return i/2 LEFT(i) return 2i RIGHT(i) return 2i + 1 IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 61/83
Heap: (Cormen) IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 62/83
Heap: Característica que distingue um Heap de uma árvore binária : A[PARENT(i)] A[i] (Max-Heap) IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 63/83
Como utilizar um Heap para Ordenar???? O Heap permite que o elemento máximo do conjunto seja determinado e corretamente posicionado no vetor em tempo constante, trocando o primeiro elemento do heap com o último. O trecho restante do vetor (do índice 1 ao n 1), que pode ter deixado de ter a estrutura de heap, volte a tê-la com número de trocas de elementos proporcional à altura da árvore. O algoritmo Heapsort consiste então da construção de um heap com os elementos a serem ordenados, seguida de sucessivas trocas do primeiro com o último elemento e rearranjos do heap. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 64/83
HeapSort(A, n) - Pseudo-Código: IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 65/83
AjustaHeap(A, i, n) - Pseudo-Código: IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 66/83
Exemplo do Funcionamento de AjustaHeap(A,2,10): IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 67/83
Exemplo do Funcionamento de AjustaHeap(A,2,10): IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 68/83
Exemplo do Funcionamento de AjustaHeap(A,2,10): IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 69/83
Complexidade do HeapSort: Quantas comparações e quantas trocas são executadas no pior caso na etapa de ordenação do algoritmo Heapsort? No pior caso, a função AjustaHeap efetua (h) comparações e trocas, onde h é a altura do heap que contém os elementos que resta ordenar. Como o heap representa uma árvore binária completa, então h Θ(log i ), onde i é o número de elementos do heap. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 70/83
Complexidade do HeapSort: Logo, a complexidade da etapa de ordenação do Heapsort é: Portanto, no pior caso, a etapa de ordenação efetua O(n log n) comparações e trocas! Mas e a construção do Heap???? IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 71/83
ConstroiHeap()\ Se o trecho de 1 a i do vetor tem estrutura de Heap, é fácil adicionar a folha i + 1 ao Heap e em seguida rearranjá-lo,garantindo que o trecho de 1 a i + 1 tem estrutura de Heap. Esta é a abordagem top-down para construção do Heap. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 72/83
ConstroiHeap(A, n) Pseudo-Código (Top-Down): IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 73/83
ConstroiHeap(A, n) (Top-Down): Quantas comparações e quantas trocas são executadas no pior caso na construção do heap pela abordagem top-down? O rearranjo do heap na iteração i efetua (h) comparações e trocas no pior caso, onde h é a altura da árvore representada pelo trecho do Heap de 1 a i. Logo, h Θ(log i ). Portanto, o número de comparações e trocas efetuadas construção do Heap por esta abordagem é: IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 74/83
Então, o algoritmo Heapsort efetua ao todo Θ (n log n) comparações e trocas no pior caso. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 75/83
Então, o algoritmo Heapsort efetua ao todo Θ (n log n) comparações e trocas no pior caso. (Bem...sendo mais preciso, executa 2 n log n comparações e trocas...) IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 76/83
Então, o algoritmo Heapsort efetua ao todo Θ (n log n) comparações e trocas no pior caso. (Bem...sendo mais preciso, executa 2 n log n comparações e trocas...) Mas existe maneira mais eficiente de construir um Heap? IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 77/83
Suponha que o trecho de i a n do vetor é tal que, para todo j, i j n, a subárvore de raiz j representada por esse trecho do vetor tem estrutura de heap. Note que, em particular, o trecho de n/2 + 1 a n do vetor satisfaz a propriedade, pois inclui apenas folhas da árvore binária de n elementos. Podemos então executar AjustaHeap(A, i 1, n), garantindo assim que o trecho de i 1 a n satisfaz a propriedade. Esta é a abordagem bottom-up para construção do Heap. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 78/83
ConstroiHeap(A, n) Pseudo-Código Alternativo...: IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 79/83
ConstroiHeap(A, 6) Exemplo: A=[2,9,7,6,5,8] IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 80/83
ConstroiHeap Complexidade: Quantas comparações e quantas trocas são executadas no pior caso na construção do Heap pela abordagem bottom-up? O(n lo g n)! Mas é possível provar matematicamente que este pior caso é O(n)... utilizando o conhecimento sobre a altura de cada sub-árvore aonde se executa o AjustaHeap(). Ainda assim, o algoritmo HeapSort() continua sendo Θ(n log n) IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 81/83
Parte Prática: Implementar os algoritmos MergeSort, QuickSort e HeapSort apresentados, rodar uma batelada de testes para medir os tempos de execução e a quantidade de comparações executada por cada algoritmo, comparando os resultados! IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 82/83
- Conclusão: Estes slides são baseados no material disponibilizado pelos profs. Cid Carvalho de Souza e Cândida Nunes da Silva, da UNICAMP. Qualquer incorretude é, entretanto, de inteira responsabilidade do prof. João Alberto Fabro, da UTFPR. IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 83/83
Prós: Dividir e Conquistar - Prós e Contras: IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 84/83
Contras: Dividir e Conquistar - Prós e Contras: IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 85/83