Projeto e Análise de Algoritmos

Documentos relacionados
Algoritmos de Ordenação: Tempo Linear

Estruturas de Dados 2

AULA 13. Algoritmos p.526/582

Projeto e Análise de Algoritmos

Ordenação em tempo linear

Análise de Algoritmos Algoritmos de Ordenação

Análise e Complexidade de Algoritmos

Estruturas de Dados 2

Aula 2. Divisão e conquista. Exemplo 1: Número de inversões de uma permutação (problema 2-4 do CLRS; veja também sec 5.4 do KT)

Análise de Algoritmos

Mergesort. Aula 04. Algoritmo Mergesort. Divisão e Conquista. Divisão e Conquista- MergeSort

Ordenação em Tempo Linear

Mediana. Aula 09. Menor. i-ésimo menor elemento. Algoritmo de Seleção. -ésimo menor elemento. Mediana é o n+1. -ésimo menor ou o n+1

Projeto e Análise de Algoritmos

Divisão e Conquista. Norton T. Roman. Apostila baseada nos trabalhos de Cid de Souza, Cândida da Silva e Delano M. Beder

Algoritmos de ordenação Quicksort

Tópico 5 Algoritmos de Ordenação. Parte II - métodos de ordenação: counting sort, radix sort e bucket sort.

Busca Binária. Aula 05. Busca em um vetor ordenado. Análise do Busca Binária. Equações com Recorrência

ANÁLISE DE ALGORITMOS

Análise de algoritmos

Projeto e Análise de Algoritmos Aula 4: Dividir para Conquistar ou Divisão e Conquista ( )

ANÁLISE DE ALGORITMOS

Algoritmos e Estrutura de Dados. Algoritmos Prof. Tiago A. E. Ferreira

Algoritmos de Ordenação: QuickSort

Ordenação. Prof. Túlio A. M. Toffolo Prof. Marco Antonio M. Carvalho BCC402 Aula 04 Algoritmos e Programação Avançada

Solução de Recorrências

Quick Sort. Considerações Sobre Algoritmos de Ordenação. Estagiário PAE: Jesimar da S. Arantes Professor: ClaudioQuick F. M.

ALGORITMOS DE ORDENAÇÃO

Projeto e Análise de Algoritmos

Melhores momentos AULA 1. Algoritmos p.38/86

Limite assintótico para a ordenação, Ordenação em tempo linear

Complexidade de Algoritmos

Universidade Estadual de Mato Grosso do Sul Bacharelado em Ciência da Computação Algoritmos e Estruturas de Dados II Prof. Fabrício Sérgio de Paula

Análise de algoritmos

Análise de Algoritmos e Estruturas de Dados

Análise de algoritmos

AED2 - Aula 11 Problema da separação e quicksort

Algoritmos de Ordenação: Cota Inferior

Projeto e Análise de Algoritmos

BCC202 - Estrutura de Dados I

ESTRUTURA DE DADOS E ALGORITMOS HEAPS E LISTAS DE PRIORIDADES

QuickSort CI/2015. Análise e Projeto de Algoritmos. - Prof. Lucídio A. F. Cabral

É interessante comparar algoritmos para valores grandes de n. Para valores pequenos de n, mesmo um algoritmo ineficiente não custa muito para ser

Análise e Síntese de Algoritmos. Revisão CLRS, Cap. 7-10

Quão rápido podemos ordenar? Aula07-LimiteInferiorpara Ordenação. Quão rápido podemos ordenar? Árvore de Decisão- Exemplo. Ordenação em Tempo Linear

Algoritmos de Ordenação

Classes, Herança e Interfaces

Algoritimos e Estruturas de Dados III CIC210

7. Introdução à Complexidade de Algoritmos

Teoria da Computação Aula 9 Noções de Complexidade

Lista 1. 8 de abril de Algorithms: Capítulo 0, exercícios 1 e 2. Tardos: Todos exercícios do cap 2 do livro texto, exceto 7 e 8 letra b.

Algoritmos de Ordenação. Cota inferior. Professora: Fátima L. S. Nunes SISTEMAS DE INFORMAÇÃO

Introdução à Análise Algoritmos

Análise de Algoritmos e Estruturas de Dados

Bubble Sort. Tempo total O(n 2 )

Algoritmos e Estrutura de Dados. Aula 04 Recorrência Prof. Tiago A. E. Ferreira

Algoritmos de Ordenação

Trabalho Prático 1. Valor: 1,0 pontos (10% da nota total) Data de Entrega: 02/05/2010

Ordenação Interna. Prof. Jonas Potros

MAC121 ALGORITMOS E ESTRUTURAS DE DADOS I 2O. SEMESTRE DE 2017

Complexidade Assintótica de Programas Letícia Rodrigues Bueno

Algoritmos de Ordenação. Profº Carlos Alberto T. Batista

Algoritmos de Ordenação: MergeSort

5. Algoritmos de Ordenação

1. O que é a eficiência assintótica de um algoritmo. Explique com suas palavras.

I. Correção de Algoritmos Não-Recursivos

Quick Sort. Considerações Sobre Algoritmos de Ordenação. Estagiário PAE: Jesimar da S. Arantes Professor: Claudio Quick F. M.

Extra- Algoritmos de Ordenação

Algoritmos gulosos (greedy)

Estruturas Discretas

Estruturas de Dados 2

Transcrição:

Projeto e Análise de Algoritmos A. G. Silva Baseado nos materiais de Souza, Silva, Lee, Rezende, Miyazawa Unicamp Ribeiro FCUP Manber, Introduction to Algorithms (989) Livro de abril de 08

Conteúdo programático Introdução (4 horas/aula) Notação Assintótica e Crescimento de Funções (4 horas/aula) Recorrências (4 horas/aula) Divisão e Conquista ( horas/aula) Buscas (4 horas/aula) Grafos (4 horas/aula) Algoritmos Gulosos (8 horas aula) Programação Dinâmica (8 horas/aula) NP-Completude e Reduções (6 horas/aula) Algoritmos Aproximados e Busca Heurística (6 horas/aula)

Cronograma 0mar Apresentação da disciplina. Introdução. 09mar Prova de proficiência/dispensa. 6mar Notação assintótica. Recorrências. mar Dia não letivo. Exercícios. 0mar Dia não letivo. Exercícios. 06abr Recorrências. Divisão e conquista. abr Divisão e conquista. Ordenação. 0abr Divisão e conquista. Estatística de ordem. 7abr Primeira avaliação. 04mai Buscas. Grafos. mai Algoritmos gulosos. 8mai Algoritmos gulosos. 5mai Programação dinâmica. 0jun Dia não letivo. Exercícios. 08jun Programação dinâmica. 5jun NP-Completude e reduções. jun Exercícios (copa). 9jun Segunda avaliação. 06jul Avaliação substitutiva (opcional).

Divisão e Conquista

Projeto de Algoritmos por Divisão e Conquista Dividir para conquistar: uma tática de guerra aplicada ao projeto de algoritmos. Um algoritmo de divisão e conquista é aquele que resolve o problema desejado combinando as soluções parciais de (um ou mais) subproblemas, obtidas recursivamente. É mais um paradigma de projeto de algoritmos baseado no princípio da indução. Informalmente, podemos dizer que o paradigma incremental representa o projeto de algoritmos por indução fraca, enquanto o paradigma de divisão e conquista representa o projeto por indução forte. É natural, portanto, demonstrar a corretude de algoritmos de divisão e conquista por indução.

Algoritmo Genérico DivisaoConquista(x) Entrada: A instância x Saída: Solução y do problema em questão para x. se x é suficientemente pequeno então Solucao(x) algoritmo para pequenas instâncias. retorne Solucao(x). senão divisão 4. decomponha x em instâncias menores x, x,, x k 5. para i de até k faça y i := DivisaoConquista(x i ) conquista 6. combine as soluções y i para obter a solução y de x. 7. retorne(y)

Projeto por Divisão e Conquista - Exemplo Exponenciação Problema: Calcular a n, para todo real a e inteiro n 0. Primeira solução, por indução fraca: Caso base: n = 0; a 0 =. Hipótese de indução: Suponha que, para qualquer inteiro n > 0 e real a, sei calcular a n. Passo da indução: Queremos provar que conseguimos calcular a n, para n > 0. Por hipótese de indução, sei calcular a n. Então, calculo a n multiplicando a n por a.

Exemplo - Solução - Algoritmo Exponenciacao(a, n) Entrada: A base a e o expoente n. Saída: O valor de a n.. se n = 0 então. retorne() {caso base}. senão 4. an := Exponenciacao(a, n ) 5. an := an a 6. retorne(an)

Exemplo - Solução - Complexidade Seja T (n) o número de operações executadas pelo algoritmo para calcular a n. Então a relação de recorrência deste algoritmo é: { c, n = 0 T (n) = T (n ) + c, n > 0, onde c e c representam, respectivamente, o tempo (constante) executado na atribuição da base e multiplicação do passo. Neste caso, não é difícil ver que T (n) = c + n c = c + nc = Θ(n). i= Este algoritmo é linear no tamanho da entrada?

Exemplo - Solução - Divisão e Conquista Vamos agora projetar um algoritmo para o problema usando indução forte de forma a obter um algoritmo de divisão e conquista. Segunda solução, por indução forte: Caso base: n = 0; a 0 =. Hipótese de indução: Suponha que, para qualquer inteiro n > 0 e real a, sei calcular a k, para todo k < n. Passo da indução: Queremos provar que conseguimos calcular a n, para n > 0. Por hipótese de indução sei calcular a n. Então, calculo a n da seguinte forma: ( a n ), se n par; a n = ( a a n ), se n ímpar.

Exemplo - Solução - Algoritmo ExponenciacaoDC(a, n) Entrada: A base a e o expoente n. Saída: O valor de a n.. se n = 0 então. retorne() {caso base}. senão divisão 4. an := ExponenciacaoDC(a, n div ) conquista 5. an := an an 6. se (n mod ) = 7. an := an a 8. retorne(an)

Exemplo - Solução - Complexidade Seja T (n) o número de operações executadas pelo algoritmo de divisão e conquista para calcular a n. Então a relação de recorrência deste algoritmo é: { c, n = 0 T (n) = T ( n ) + c, n > 0, Não é difícil ver que T (n) Θ(log n). Por quê?

Projeto por Divisão e Conquista - Exemplo Busca Binária Problema: Dado um vetor ordenado A com n números reais e um real x, determinar a posição i n tal que A[i] = x, ou que não existe tal i. O projeto de um algoritmo para este problema usando indução simples, nos leva a um algoritmo incremental de complexidade de pior caso Θ(n). Pense em como seria a indução! Se utilizarmos indução forte para projetar o algoritmo, podemos obter um algoritmo de divisão e conquista que nos leva ao algoritmo de busca binária. Pense na indução! Como o vetor está ordenado, conseguimos determinar, com apenas uma comparação, que metade das posições do vetor não pode conter o valor x.

Exemplo - Algoritmo BuscaBinaria(A, e, d, x) Entrada: Vetor A, delimitadores e e d do subvetor e x. Saída: Índice i n tal que A[i] = x ou i = 0.. se e = d então se A[e] = x então retorne(e). senão retorne(0). senão 4. i := (e + d) div 5. se A[i] = x retorne(i) 6. senão se A[i] > x 7. i := BuscaBinaria(A, e, i, x) 8. senão {A[i] < x} 9. i := BuscaBinaria(A, i +, d, x). retorne(i)

Exemplo - Complexidade O número de operações T (n) executadas na busca binária no pior caso é: { c, n = T (n) = T ( n ) + c, n >, Não é difícil ver que T (n) Θ(log n). Por quê? O algoritmo de busca binária (divisão e conquista) tem complexidade de pior caso Θ(log n), que é assintoticamente melhor que o algoritmo de busca linear (incremental). E se o vetor não estivesse ordenado, qual paradigma nos levaria a um algoritmo assintoticamente melhor?

Projeto por Divisão e Conquista - Exemplo - Máximo e Mínimo Problema: Dado um conjunto S de n números reais, determinar o maior e o menor elemento de S. Um algoritmo incremental para esse problema faz n comparações: fazemos uma comparação no caso base e duas no passo. Será que um algoritmo de divisão e conquista seria melhor? Um possível algoritmo de divisão e conquista seria: Divida S em dois subconjuntos de mesmo tamanho S e S e solucione os subproblemas. O máximo de S é o máximo dos máximos de S e S e o mínimo de S é o mínimo dos mínimos de S e S.

Exemplo - Complexidade Qual o número de comparações T (n) efetuado por este algoritmo? {, n = T (n) = T ( n ) + T ( n ) +, n >, Supondo que n é uma potência de, temos: {, n = T (n) = T ( n ) +, n >, Neste caso, podemos provar que T (n) = n usando o método da substituição (indução!).

Exemplo - Complexidade Caso Base: T () = =. Hipótese de Indução: Suponha, para n = k, k, que T (n) = n. Passo de Indução: Queremos provar para n = k, k, que T (n) = n. T (n) = T ( n ) + = ( 4n ) + (por h. i.) = n. É possível provar que T (n) = n quando n não é potência de?

Exemplo - Complexidade Assintoticamente, os dois algoritmos para este problema são equivalentes, ambos Θ(n). No entanto, o algoritmo de divisão e conquista permite que menos comparações sejam feitas. A estrutura hierárquica de comparações no retorno da recursão evita comparações desnecessárias.

QuickSort O algoritmo QUICKSORT segue o paradigma de divisão-e-conquista. Divisão: divida o vetor em dois subvetores A[p...q ] e A[q +...r] tais que p q r A x x > x A[p...q ] A[q] < A[q +...r] Conquista: ordene os dois subvetores recursivamente usando o QUICKSORT; Combinação: nada a fazer, o vetor está ordenado.

Partição Problema: Rearranjar um dado vetor A[p...r] edevolverum í n d i c e q, p q r, taisque Entrada: A[p...q ] A[q] < A[q +...r] p r A 99 55 77 88 66 44 Saída: p q r A 44 55 99 66 77 88

Particione p r A i 99 j 55 77 88 66 44 x A 99 55 77 88 66 44 i j x A 99 55 77 88 66 44 i j x A 99 55 77 88 66 44 i j x A 99 55 77 88 66 44 i j x A 99 55 77 88 66 44 i j x A 55 77 99 88 66 44

Particione i j x A 55 77 99 88 66 44 i j x A 77 99 55 88 66 44 i j x A 77 99 55 88 66 44 i j x A 77 99 55 88 66 44 i j A 99 55 88 66 77 44 p q r A 44 55 88 66 77 99

Particione Rearranja A[p...r] de modo que p q r e A[p...q ] A[q] < A[q+...r] PARTICIONE(A, p, r) x A[r] x éo pivô i p para j p até r faça 4 se A[j] x 5 então i i + 6 A[i] A[j] 7 A[i+] A[r] 8 devolva i + Invariantes: No começo de cada iteração da linha vale que: () A[p...i] x () A[i+...j ] > x () A[r] =x

Complexidade de PARTICIONE PARTICIONE(A, p, r) Tempo x A[r] x éo pivô? i p? para j p até r faça? 4 se A[j] x? 5 então i i +? 6 A[i] A[j]? 7 A[i+] A[r]? 8 devolva i +? T (n) = complexidade de tempo no pior caso sendo n := r p +

Complexidade de PARTICIONE PARTICIONE(A, p, r) Tempo x A[r] x éo pivô Θ() i p Θ() para j p até r faça Θ(n) 4 se A[j] x Θ(n) 5 então i i + O(n) 6 A[i] A[j] O(n) 7 A[i+] A[r] Θ() 8 devolva i + Θ() T (n) = Θ(n + 4)+ O(n) = Θ(n) Conclusão: AcomplexidadedePARTICIONE é Θ(n).

QuickSort Rearranja um vetor A[p...r] em ordem crescente. QUICKSORT(A, p, r) se p < r então q PARTICIONE(A, p, r) QUICKSORT(A, p, q ) 4 QUICKSORT(A, q +, r) p r A 99 55 77 88 66 44

QuickSort Rearranja um vetor A[p...r] em ordem crescente. QUICKSORT(A, p, r) se p < r então q PARTICIONE(A, p, r) QUICKSORT(A, p, q ) 4 QUICKSORT(A, q +, r) p q r A 44 55 88 66 77 99 No começo da linha, A[p...q ] A[q] < A[q+...r]

QuickSort Rearranja um vetor A[p...r] em ordem crescente. QUICKSORT(A, p, r) se p < r então q PARTICIONE(A, p, r) QUICKSORT(A, p, q ) 4 QUICKSORT(A, q +, r) p q r A 44 55 88 66 77 99

QuickSort Rearranja um vetor A[p...r] em ordem crescente. QUICKSORT(A, p, r) se p < r então q PARTICIONE(A, p, r) QUICKSORT(A, p, q ) 4 QUICKSORT(A, q +, r) p q r A 44 55 66 77 88 99

Complexidade de QUICKSORT QUICKSORT(A, p, r) Tempo se p < r? então q PARTICIONE(A, p, r)? QUICKSORT(A, p, q )? 4 QUICKSORT(A, q +, r)? T (n) := complexidade de tempo no pior caso sendo n := r p +

Complexidade de QUICKSORT QUICKSORT(A, p, r) Tempo se p < r Θ() então q PARTICIONE(A, p, r) Θ(n) QUICKSORT(A, p, q ) T (k) 4 QUICKSORT(A, q +, r) T (n k ) T (n) = T (k)+t (n k )+Θ(n + ) 0 k := q p n

Recorrência T (n) :=consumo de tempo no pior caso T (0) =Θ() T () =Θ() T (n) =T (k)+t (n k )+Θ(n) para n =,, 4,... Recorrência grosseira: T (n) =T (0)+T(n )+Θ(n) T (n) é Θ(???). Recorrência grosseira: T (n) =T (0)+T(n )+Θ(n) T (n) é Θ(n ).

Recorrência cuidadosa T (n) :=complexidade de tempo no pior caso T (0) =Θ() T () =Θ() T (n) = max {T (k)+t(n k )} + Θ(n) para n =,, 4,... 0 k n T (n) =max 0 k n {T (k)+t (n k )} + bn Quero mostrar que T (n) =Θ(n ).

Demonstração T (n) =O(n ) Vou provar que T (n) cn para n grande. { T (n) = max T (k) + T (n k ) 0 k n } {ck + c(n k ) max 0 k n = c max 0 k n {k + (n k ) } = c(n ) + bn exercício = cn cn + c + bn cn, se c > b/ en c/(c b). } + bn + bn + bn

Continuação T (n) =Ω(n ) Agora vou provar que T (n) dn para n grande. { } T (n) = max T (k) + T (n k ) + bn 0 k n } {dk + d(n k ) max 0 k n = d max 0 k n = d(n ) + bn = dn dn + d + bn dn, se d < b/ en d/(d b). {k + (n k ) } + bn + bn

Conclusão T (n) é Θ(n ). A complexidade de tempo do QUICKSORT no pior caso é Θ(n ). AcomplexidadedetempodoQUICKSORT é O(n ).

QuickSort no melhor caso M(n) :=complexidade de tempo no melhor caso M(0) =Θ() M() =Θ() M(n) = min {M(k)+M(n k )} + Θ(n) para n =,, 4,... 0 k n Mostre que, para n, M(n) (n ) lg n. Isto implica que no melhor caso o QUICKSORT é Ω(n lg n). Que éomesmoquedizerqueoquicksort é Ω(n lg n).

QuickSort no melhor caso No melhor caso k éaproximadamente(n )/. n n R(n) =R( )+R( )+Θ(n) Solução: R(n) é Θ(n lg n). Humm, lembra a recorrência do MERGESORT...

Mais algumas conclusões M(n) é Θ(n lg n). O consumo de tempo do QUICKSORT no melhor caso é Ω(n log n). Mais precisamente, a complexidade de tempo do QUICKSORT no melhor caso é Θ(n log n).

Caso médio Apesar da complexidade de tempo do QUICKSORT no pior caso ser Θ(n ),naprática ele éoalgoritmomaiseficiente. Mais precisamente, a complexidade de tempo do QUICKSORT no caso médio émaispróximo do melhor caso do que do pior caso. Por quê?? Suponha que (por sorte) o algoritmo PARTICIONE sempre divide o vetor na proporção 9 para 9.Então n 9(n ) T (n) =T ( 9 )+T ( )+Θ(n) Solução: T (n) é Θ(n lg n).

Árvore de recorrência n n 9n n 0 9n 0 9n 0 8n 0 8n 00 8n 00 79n 00 Número de níveis log /9 n. Em cada nível o custo é n. Custo total é O(n log n).

QuickSort Aleatório O pior caso do QUICKSORT ocorre devido a uma escolha infeliz do pivô. Um modo de minimizar este problema éusaraleatoriedade. PARTICIONE-ALEATÓRIO(A, p, r) i RANDOM(p, r) A[i] A[r] devolva PARTICIONE(A, p, r) QUICKSORT-ALEATÓRIO(A, p, r) se p < r então q PARTICIONE-ALEATÓRIO(A, p, r) QUICKSORT-ALEATÓRIO(A, p, q ) 4 QUICKSORT-ALEATÓRIO(A, q +, r)

Análise do caso médio Recorrência para o caso médio do algoritmo QUICKSORT-ALEATÓRIO. T (n) =consumo de tempo médio do algoritmo QUICKSORT-ALEATÓRIO. PARTICIONE-ALEATÓRIO rearranja o vetor A edevolveum í n d i c e q tal que A[p...q ] A[q] e A[q +...r] > A[q]. T (0) =Θ() T (n) é Θ(???). T () =Θ() ( T (n) = n ) (T (k)+t(n k)) + Θ(n). n k=0

Análise do caso médio T (n) = n = n ( n ) (T (k)+t(n k)) + cn k=0 n k=0 T (k)+cn. Vou mostrar que T (n) é O(n lg n). Vou mostrar que T (n) an lg n + b para n ondea, b > 0 são constantes.

Demonstração T (n) n = a n n k=0 T (k)+cn n (ak lg k + b)+cn n k=0 n k= k lg k + b + cn Lema n k lg k n lg n 8 n. k=

Demonstração T (n) = a n a n n k= k lg k + b + cn ( n lg n ) 8 n + b + cn = an lg n a n + b + cn 4 = an lg n + b + (cn + b a ) 4 n an lg n + b, escolhendo a de modo que a 4n cn + b para n.

Prova do Lema n k lg k = k= n/ k= k lg k + n k= n/ k lg k n/ (lg n ) k + lg n k= n n/ = lg n k k k= k= n(n ) lg n n k= n/ ( n ) n k n lg n 8 n

Conclusão OconsumodetempodeQUICKSORT-ALEATÓRIO no caso médio é O(n lg n). Exercício Mostre que T (n) =Ω(n lg n). Conclusão: OconsumodetempodeQUICKSORT-ALEATÓRIO no caso médio é Θ(n lg n).

Ordenação outros métodos importantes

Algoritmos de ordenação Algoritmos de ordenação: Insertion sort Selection sort Mergesort Quicksort Heapsort Algoritmos lineares: Counting sort Radix sort

Heapsort O Heapsort éumalgoritmodeordenação que usa uma estrutura de dados sofisticada chamada heap. Acomplexidadedepiorcasoé Θ(n lg n). Heaps podem ser utilizados para implementar filas de prioridade que são extremamente úteis em outros algoritmos. Um heap éumvetora que simula uma árvore binária completa, comexceção possivelmente do último nível.

Heaps nível 0 4 5 6 7 8 9 4 5 6 7 8 9

Heaps Considere um vetor A[...n] representando um heap. Cada posição do vetor corresponde a um nó do heap. O pai de um nó i é i/. Onó não tem pai.

Heaps Um nó i tem i como filho esquerdo e i + como filho direito. Naturalmente, o nó i tem filho esquerdo apenas se i n e tem filho direito apenas se i + n. Um nó i éumafolha se não tem filhos, ou seja, se i > n. As folhas são n/ +,...,n, n.

Níveis Cada nível p, excetotalvezoúltimo,temexatamente p nós e esses são p, p +, p +,..., p+. Onó i pertence ao nível???. Onó i pertence ao nível lg i. Prova: Se p éoníveldonó i, então Logo, p = lg i. p i < p+ lg p lg i < lg p+ p lg i < p + Portanto o número total de níveis é???. Portanto, o número total de níveis é + lg n.

Altura A altura de um nó i éomaior comprimento de um caminho de i aumafolha. Os nós que têm altura zero são as folhas. Qual éaalturadeumnó i?

Altura Aalturadeumnó i éocomprimentodaseqüência onde h i n < (h+) i. i, i, i,..., h i Assim, h i n < h+ i h n/i < h+ h lg(n/i) < h + Portanto, a altura de i é lg(n/i).

Max-heaps Um nó i satisfaz a propriedade de (max-)heap se A[ i/ ] A[i] (ou seja, pai filho). Uma árvore binária completa éummax-heap se todo nó distinto da raiz satisfaz a propriedade de heap. O máximo ou maior elemento de um max-heap está na raiz.

Max-heap 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 5 5 46 46 7 7 4 4 4 4 5 5 4 4 0 0

Min-heaps Um nó i satisfaz a propriedade de (min-)heap se A[ i/ ] A[i] (ou seja, pai filho). Uma árvore binária completa éummin-heap se todo nó distinto da raiz satisfaz a propriedade de min-heap. Vamos nos concentrar apenas em max-heaps. Os algoritmos que veremos podem ser facilmente modificados para trabalhar com min-heaps.

Manipulação de max-heap 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 46 46 7 7 4 4 4 4 5 5 4 4 0 0

Manipulação de max-heap 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 46 46 7 7 4 4 4 4 5 5 4 4 0 0

Manipulação de max-heap 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 46 46 4 4 7 7 4 4 5 5 4 4 0 0

Manipulação de max-heap 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 46 46 4 4 7 7 4 4 5 5 4 4 0 0

Manipulação de max-heap 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 46 46 4 4 7 7 4 4 5 5 4 4 0 0

Manipulação de max-heap Recebe A[...n] e i taisquesubárvores com raízes i e i + são max-heaps e rearranja A de modo que subárvore com raiz i seja um max-heap. MAX-HEAPIFY(A, n, i ) e i d i + se e n e A[e] > A[i] 4 então maior e 5 senão maior i 6 se d n e A[d] > A[maior] 7 então maior d 8 se maior i 9 então A[i] A[maior] MAX-HEAPIFY(A, n, maior)

Corretude de MAXHEAPIFY A corretude de MAX-HEAPIFY segue por indução na altura h do nó i. Base: para h =, o algoritmo funciona. Hipótese de indução: MAX-HEAPIFY funciona para heaps de altura < h. Passo de indução: Avariável maior na linha 8 guarda o índice do maior elemento entre A[i], A[i] e A[i + ]. Após a troca na linha 9, temos A[i], A[i + ] A[i]. O algoritmo MAX-HEAPIFY transforma a subárvore com raiz maior em um max-heap (hipótese de indução).

Corretude de MAXHEAPIFY Passo de indução: Avariável maior na linha 8 guarda o índice do maior elemento entre A[i], A[i] e A[i + ]. Após a troca na linha 9, temos A[i], A[i + ] A[i]. O algoritmo MAX-HEAPIFY transforma a subárvore com raiz maior em um max-heap (hipótese de indução). A subárvore cuja raiz é o irmão de maior continua sendo um max-heap. Logo, a subárvore com raiz i torna-se um max-heap e portanto, oalgoritmomax-heapify está correto.

Complexidade de MAXHEAPIFY MAX-HEAPIFY(A, n, i ) Tempo e i? d i +? se e n e A[e] > A[i]? 4 então maior e? 5 senão maior i? 6 se d n e A[d] > A[maior]? 7 então maior d? 8 se maior i? 9 então A[i] A[maior]? MAX-HEAPIFY(A, n, maior)? h := altura de i = lg n i T (h) := complexidade de tempo no pior caso

Complexidade de MAXHEAPIFY MAX-HEAPIFY(A, n, i ) Tempo e i Θ() d i + Θ() se e n e A[e] > A[i] Θ() 4 então maior e O() 5 senão maior i O() 6 se d n e A[d] > A[maior] Θ() 7 então maior d O() 8 se maior i Θ() 9 então A[i] A[maior] O() MAX-HEAPIFY(A, n, maior) T (h ) h := altura de i = lg n i T (h) T (h )+Θ(5)+O().

Complexidade de MAXHEAPIFY h := altura de i = lg n i T (h) := complexidade de tempo no pior caso T (h) T (h )+Θ() Solução assintótica: T (n) é???. Solução assintótica: T (n) é O(h). Como h lg n, podemosdizerque: OconsumodetempodoalgoritmoMAX-HEAPIFY é O(lg n) (ou melhor ainda, O(lg n i )).

Construção de um max-heap nível 4 0 4 4 5 6 7 7 5 46 8 9 4 0 4 5 6 7 8 9 4 4 7 5 46 4 0

Construção de um max-heap nível 46 0 4 4 4 5 6 7 0 4 8 9 7 5 4 5 6 7 8 9 46 4 4 0 4 7 5

Construção de um max-heap Recebe um vetor A[...n] erearranjaa para que seja max-heap. BUILDMAXHEAP(A, n) para i n/ decrescendo até faça MAX-HEAPIFY(A, n, i ) Invariante: No início de cada iteração, i +,...,n são raízes de max-heaps. T (n) =complexidade de tempo no pior caso Análise grosseira: T (n) é n O(lg n) =O(n lg n).

Construção de um max-heap Análise mais cuidadosa: T (n) é O(n). Na iteração i são feitas O(h i ) comparações e trocas no pior caso, onde h i éaalturadasubárvore de raiz i. Seja S(h) asomadasalturasdetodososnós de uma árvore binária completa de altura h. Aalturadeumheapé lg n +. AcomplexidadedeBUILDMAXHEAP é T (n) =O(S(lg n)).

Construção de um max-heap Pode-se provar por indução que S(h) = h+ h. Logo, a complexidade de BUILDMAXHEAP é T (n) =O(S(lg n)) = O(n). Mais precisamente, T (n) =Θ(n). (Por quê?) Veja no CLRS uma prova diferente deste fato.

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 46 46 4 4 4 4 0 0 4 4 7 7 5 5

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 4 4 4 4 0 0 4 4 7 7 5 5 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 4 4 4 4 0 0 4 4 7 7 5 5 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 4 4 0 0 4 4 4 4 7 7 5 5 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 4 4 0 0 4 4 5 5 4 4 7 7 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 4 4 0 0 4 4 5 5 4 4 7 7 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 0 0 4 4 5 5 4 4 7 7 4 4 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 0 0 4 4 5 5 4 4 7 7 4 4 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 4 4 0 0 5 5 4 4 7 7 4 4 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 4 4 0 0 5 5 4 4 7 7 4 4 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 4 4 0 0 5 5 4 4 7 7 4 4 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 0 0 5 5 4 4 7 7 4 4 4 4 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 0 0 5 5 4 4 7 7 4 4 4 4 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 0 0 5 5 4 4 7 7 4 4 4 4 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 0 0 5 5 4 4 7 7 4 4 4 4 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 0 0 7 7 5 5 4 4 4 4 4 4 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 0 0 7 7 5 5 4 4 4 4 4 4 46 46

HeapSort 4 4 5 5 6 6 7 7 8 8 9 9 nível 0 7 7 5 5 4 4 0 0 4 4 4 4 46 46

HeapSort Algoritmo rearranja A[...n] em ordem crescente. HEAPSORT(A, n) BUILD-MAX-HEAP(A, n) m n para i n decrescendo até faça 4 A[] A[i] 5 m m 6 MAX-HEAPIFY(A, m, ) Invariantes: No início de cada iteração na linha vale que: A[m...n] écrescente; A[...m] A[m + ]; A[...m] éummax-heap.

HeapSort Algoritmo rearranja A[...n] em ordem crescente. HEAPSORT(A, n) Tempo BUILD-MAX-HEAP(A, n)? m n? para i n decrescendo até faça? 4 A[] A[i]? 5 m m? 6 MAX-HEAPIFY(A, m, )? T (n) = complexidade de tempo no pior caso

HeapSort Algoritmo rearranja A[...n] em ordem crescente. HEAPSORT(A, n) Tempo BUILD-MAX-HEAP(A, n) Θ(n) m n Θ() para i n decrescendo até faça Θ(n) 4 A[] A[i] Θ(n) 5 m m Θ(n) 6 MAX-HEAPIFY(A, m, ) no(lg n) T (n) =?? T (n) =no(lg n)+θ(4n + ) =O(n lg n) AcomplexidadedeHEAPSORT no pior caso é O(n lg n). Como seria a complexidade de tempo no melhor caso?

Filas com prioridades Uma fila com prioridades é um tipo abstrato de dados que consiste de uma coleção S de itens, cada um com um valor ou prioridade associada. Algumas operações típicas em uma fila com prioridades são: MAXIMUM(S): devolve o elemento de S com a maior prioridade; EXTRACT-MAX(S): remove e devolve o elemento em S com a maior prioridade; INCREASE-KEY(S, x, p): aumenta o valor da prioridade do elemento x para p; e INSERT(S, x, p): insere o elemento x em S com prioridade p.

Implementação com max-heap HEAP-MAX(A, n) devolva A[] Complexidade de tempo: Θ(). HEAP-EXTRACT-MAX(A, n) n max A[] A[] A[n] 4 cor n 5 MAX-HEAPIFY (A, n, ) 6 devolva max Complexidade de tempo: O(lg n).

Implementação com max-heap HEAP-INCREASE-KEY(A, i, prior) Supõe que prior A[i] A[i] prior enquanto i > ea[ i/ ] < A[i] faça 4 A[i] A[ i/ ] 5 i i/ Complexidade de tempo: O(lg n). MAX-HEAP-INSERT(A, n, prior) n n + A[n] HEAP-INCREASE-KEY(A, n, prior) Complexidade de tempo: O(lg n).

Ordenação em Tempo Linear

Algoritmos lineares para ordenação Os seguintes algoritmos de ordenação têm complexidade O(n): Counting Sort: Elementos são números inteiros pequenos ; maisprecisamente,inteirosx O(n). Radix Sort: Elementos são números inteiros de comprimento máximo constante, isto é, independente de n. Bucket Sort: Elementos são números reais uniformemente distribuídos no intervalo [0..).

Counting Sort Considere o problema de ordenar um vetor A[...n] de inteiros quando se sabe que todos os inteiros estão no intervalo entre 0 e k. Podemos ordenar o vetor simplesmente contando, para cada inteiro i no vetor, quantos elementos do vetor são menores que i. ÉexatamenteoquefazoalgoritmoCounting Sort.

Counting Sort COUNTING-SORT(A, B, n, k ) para i 0 até k faça C[i] 0 para j até n faça 4 C[A[j]] C[A[j]] + C[i] éonúmerodejs taisquea[j] =i 5 para i até k faça 6 C[i] C[i]+C[i ] C[i] éonúmerodejs taisquea[j] i 7 para j n decrescendo até faça 8 B[C[A[j]]] A[j] 9 C[A[j]] C[A[j]]

Counting Sort -Complexidade Qual a complexidade do algoritmo COUNTING-SORT? Oalgoritmonão faz comparações entre elementos de A! Sua complexidade deve ser medida em função do número das outras operações, aritméticas, atribuições, etc. Claramente, a complexidade de COUNTING-SORT é O(n + k). Quandok O(n), eletemcomplexidadeo(n). Há algodeerradocomolimiteinferiordeω(n log n) para ordenação?

Algoritmos in-place e estáveis Algoritmos de ordenação podem ser ou não in-place ou estáveis. Um algoritmo de ordenação é in-place se a memória adicional requerida éindependentedotamanhodovetor que está sendoordenado. Exemplos: QUICKSORT e HEAPSORT são métodos de ordenação in-place, já MERGESORT e COUNTING-SORT não são. Um método de ordenação é estável se elementos iguais ocorrem no vetor ordenado na mesma ordem em que são passados na entrada. Exemplos: COUNTING-SORT e QUICKSORT são exemplos de métodos estáveis (desde que certos cuidados sejam tomados na implementação). HEAPSORT não é.

Radix Sort Considere agora o problema de ordenar um vetor A[...n] inteiros quando se sabe que todos os inteiros podem ser representados com apenas d dígitos, onde d é uma constante. Por exemplo, os elementos de A podem ser CEPs, ou seja, inteiros de 8 dígitos.

Radix Sort Poderíamos ordenar os elementos do vetor dígito a dígito da seguinte forma: Separamos os elementos do vetor em grupos que compartilham o mesmo dígito mais significativo. Em seguida, ordenamos os elementos em cada grupo pelo mesmo método, levando em consideração apenas os d dígitos menos significativos. Esse método funciona, mas requer o uso de bastante memória adicional para a organização dos grupos e subgrupos.

Radix Sort Podemos evitar o uso excessivo de memória adicional começando pelo dígito menos significativo. ÉissooquefazoalgoritmoRadix Sort. Para que Radix Sort funcione corretamente, ele deve usar um método de ordenação estável. Por exemplo, o COUNTING-SORT.

Radix Sort Suponha que os elementos do vetor A aserordenadosejam números inteiros de até d dígitos. O Radix Sort é simplesmente: RADIX-SORT(A, n, d ) para i até d faça Ordene A[...n] pelo i-ésimo dígito usando um método estável

Radix Sort -Exemplo 9 457 657 89 46 70 55 70 55 46 457 657 9 89 70 9 46 89 55 457 657 9 55 46 457 657 70 89

Radix Sort -Corretude Oseguinteargumentoindutivogaranteacorretudedo algoritmo: Hipótese de indução: os números estão ordenados com relação aos i dígitos menos significativos. Oqueaconteceaoordenarmospeloi-ésimo dígito? Se dois números têm i-ésimo dígitos distintos, o de menor i-ésimo dígito aparece antes do de maior i-ésimo dígito. Se ambos possuem o mesmo i-ésimo dígito, então a ordem dos dois também estará corretapoisométodo de ordenação é estável e, pela HI, osdoiselementosjá estavam ordenados segundo os i dígitos menos significativos.

Radix Sort -Complexidade Qual éacomplexidadederadix-sort? Depende da complexidade do algoritmo estável usado para ordenar cada dígito. Se essa complexidade for Θ(f (n)), obtemosuma complexidade total de Θ(d f(n)). Como d éconstante,acomplexidadeéentão Θ(f (n)). Se o algoritmo estável for, por exemplo, o COUNTING-SORT, obtemosacomplexidadeθ(n + k). Se k O(n), istoresultaemumacomplexidadelinearem n. EolimiteinferiordeΩ(n log n) para ordenação?

Radix Sort -Complexidade Em contraste, um algoritmo por comparação como o MERGESORT teria complexidade Θ(n lg n). Assim, RADIX-SORT émaisvantajosoquemergesort quando d < lg n, ouseja,onúmerodedígitosformenor que lg n. Se n for um limite superior para o maior valor a ser ordenado, então O(log n) éumaestimativaparaa quantidade de dígitos dos números. Isso significa que não há diferença significativa entre o desempenho do MERGESORT edoradix-sort?

Radix Sort -Complexidade O nome Radix Sort vem da base (em inglês radix) em que intepretamos os dígitos. A vantagem de se usar RADIX-SORT fica evidente quando interpretamos os dígitos de forma mais geral que simplesmente 0..9. Tomemos o seguinte exemplo: suponha que desejemos ordenar um conjunto de n = 0 números de 64 bits. Então, MERGESORT faria cerca de n lg n = 0 0 comparações e usaria um vetor auxiliar de tamanho 0.

Radix Sort -Complexidade Agora suponha que interpretamos cada número do como tendo d = 4dígitosem base k = 6,eusarmos RADIX-SORT com o Counting Sort como método estável. Então a complexidade de tempo seria da ordem de d(n + k) =4( 0 + 6 ) operações, bem menor que 0 0 do MERGESORT. Mas,notequeutilizamosdois vetores auxiliares, de tamanhos 6 e 0. Se o uso de memória auxiliar for muito limitado, então o melhor mesmo éusarumalgoritmodeordenação por comparação in-place. Note que épossívelusaroradix Sort para ordenar outros tipos de elementos, como datas, palavras em ordem lexicográfica e qualquer outro tipo que possa ser visto como uma d-upla ordenada de itens comparáveis.