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

Documentos relacionados
Aula 1. Teoria da Computação III

ESTRUTURAS DE DADOS prof. Alexandre César Muniz de Oliveira

Medida do Tempo de Execução de um Programa. David Menotti Algoritmos e Estruturas de Dados II DInf UFPR

Medida do Tempo de Execução de um Programa

ANÁLISE DE ALGORITMOS: PARTE 3

Algoritmo. Exemplo. Definição. Programação de Computadores Comparando Algoritmos. Alan de Freitas

Análise de Algoritmos

Complexidade de algoritmos Notação Big-O

Análise de Algoritmos

Quantidade de memória necessária

BCC202 - Estrutura de Dados I

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

Análise de Algoritmos Estrutura de Dados II

Complexidade de Algoritmos

COMPLEXIDADE DE ALGORITMOS

CES-11. Noções de complexidade de algoritmos. Complexidade de algoritmos. Avaliação do tempo de execução. Razão de crescimento desse tempo.

Análise de complexidade

Complexidade assintótica de programas

ANÁLISE DE COMPLEXIDADE DOS ALGORITMOS

Análise de Complexidade para algoritmos iterativos e recursivos

Análise de Algoritmos

Análise e Complexidade de Algoritmos

Teoria da Computação. Aula 3 Comportamento Assintótico 5COP096. Aula 3 Prof. Dr. Sylvio Barbon Junior. Sylvio Barbon Jr

Teoria dos Grafos Aula 7

CT-234. Estruturas de Dados, Análise de Algoritmos e Complexidade Estrutural. Carlos Alberto Alonso Sanches

Melhores momentos AULA 1. Algoritmos p.38/86

Solução de Recorrências

Análise de algoritmos

Análise de algoritmos

Área que visa determinar a complexidade (custo) de um algoritmo, com isso é possível:

Técnicas de análise de algoritmos

COMPLEXIDADE DE ALGORITMOS COMPLEXIDADE DE ALGORITMOS

INF 1010 Estruturas de Dados Avançadas

Análise de algoritmos

Projeto e Análise de Algoritmos

BCC202 - Estrutura de Dados I

Noções de complexidade de algoritmos

Análise e Projeto de Algoritmos

Complexidade de Algoritmos

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. Parte I

Projeto de Algoritmos Introdução

BCC202 - Estrutura de Dados I

7. Introdução à Complexidade de Algoritmos

Análise de Complexidade de Algoritmos

Projeto e Análise de Algoritmos

2. Complexidade de Algoritmos

ESTRUTURA DE DADOS CIÊNCIA E TECNOLOGIA DO RIO. Curso de Tecnologia em Sistemas para Internet

ANÁLISE DE ALGORITMOS

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

Elementos de Análise Assintótica

Estruturas de Dados Algoritmos

Projeto e Análise de Algoritmos

5. Análise de Complexidade de Algoritmos. João Pascoal Faria (versão original) Ana Paula Rocha (versão 2003/2004) Luís Paulo Reis (versão 2005/2006)

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

Análise de Complexidade de Algoritmos. mario alexandre gazziro

Análise de algoritmos. Parte I

Comportamento assintótico

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

Análise de Problemas Recursivos. Algoritmos e Estruturas de Dados Flavio Figueiredo (

Capítulo 6 Análise de Algoritmos Capítulo 6

03 Análise de Algoritmos (parte 3) SCC201/501 - Introdução à Ciência de Computação II

Introdução à Ciência da Computação II

Algoritmos 3/17/ Algoritmos como área de estudo e investigação

INF 1010 Estruturas de Dados Avançadas

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

Algoritmos de Ordenação

SCC Capítulo 3 Análise de Algoritmos - Parte 2

Capítulo. Análise de Algoritmos. 6.1 Complexidade de Algoritmos 6.1

Comportamento Assintótico. Algoritmos e Estruturas de Dados Flavio Figueiredo (

Algoritmos e Complexidade

Algoritmos Avançados Análise de Complexidade

Introdução à Análise de Algoritmos

Algoritmos e Estruturas de Dados I Aula 06 Custos de um algoritmo

Estruturas de Dados 2

Belo Horizonte PROGRAMAÇÃO MODULAR. Volume V. Estruturas de Dados Fundamentais. Roberto S. Bigonha

ALGORITMOS E ESTRUTURAS DE DADOS 2011/2012 ANÁLISE DE ALGORITMOS. Armanda Rodrigues 3 de Outubro 2011

ANÁLISE DE ALGORITMOS: PARTE 4

Análise e Projeto de Algoritmos

Análise de algoritmos Parte I

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

Complexidade Assintótica de Programas Letícia Rodrigues Bueno

7. Introdução à Complexidade de Algoritmos

Projeto de Algoritmos Introdução

Teoria dos Grafos. Valeriano A. de Oliveira Socorro Rangel Departamento de Matemática Aplicada.

Nem todos os problemas algorítmicos que podem ser resolvidos em princípio podem ser resolvidos na prática: os recursos computacionais requeridos

Breve Introdução à Complexidade Assintótica de Algoritmos Letícia Rodrigues Bueno

Algoritmos de Ordenação

Técnicas de projeto de algoritmos: Indução

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)

BC1424 Algoritmos e Estruturas de Dados I Aula 05 Custos de um algoritmo e funções de complexidade

André Vignatti DINF- UFPR

Técnicas de Projeto de Algoritmos

Complexidade de Algoritmos

Programação II Aula 07

Projeto de Algoritmos Introdução

ALGORITMOS AVANÇADOS UNIDADE I Análise de Algoritmo - Notação O. Luiz Leão

Teoria da computabilidade Indecidíveis Decidíveis

Algoritmos de Ordenação: MergeSort

Transcrição:

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

Fazendo estimativas e simplificações... O número de passos que um algoritmo dá para uma dada entrada pode depender de vários parâmetros: Se for um grafo pode depender do número de nós, arestas, grau máximo do grafo, ou uma combinação destes. Mas, por simplicidade, computamos o tempo de execução em função da entrada (que em grafos geralmente é o número de nós) e desconsideramos os outros parâmetros. Além disso, usamos uma estimativa a análise assintótica que somente considera o termo de ordem mais alta de uma expressão para o tempo de execução Por exemplo, para f(n) = 6 n 3 + 2 n 2 + 20 n + 45 consideramos 6n3 e descartamos o coeficiente 6 e dizemos que f(n) = O(n 3 ). 2

Objetivos: Introdução Apresentar as notações assintóticas usadas para descrever a taxa de crescimento de funções de custo de algoritmos Tópicos: Notação O big-oh Notação - ômega Notação - theta Classes de comportamento assintótico Algoritmo Exponencial versus Polinomial Como calcular a complexidade de limite superior (big Oh) de algoritmos 3

Custo Assintótico de Funções O custo assintótico de uma função f(n) representa o limite do comportamento de custo quando n cresce. Geralmente, um algoritmo que é assintoticamente mais eficiente será a melhor escolha para valores grandes de n. 4

Dominação Assintótica Definição: f(n) domina assintoticamente g(n) se existem duas constantes positivas c e m tais que, para n >= m, temos g(n) <= c. f(n) c.f(n) g(n) m Exemplo: Seja g(n) = n e f(n) = -n 2 Temos que n <= -n 2 para todo n pertencente aos N. Fazendo c = 1 e m = 0 a definição é satisfeita. Logo, f(n) domina assintoticamente g(n) n 5

Notação O Notação trazida da matemática por Knuth (1968): g(n) = O(f(n)) Lê-se: g(n) é de ordem no máximo f(n) f(n) domina assintoticamente g(n) (f(n) é um limite assintótico superior para g(n)) O(f(n)) representa o conjunto de todas as funções que são assintoticamente dominadas por uma dada função f(n). Se g(n) O(f(n)) então dizemos g(n) = O(f(n)) Formalmente: g(n) = O(f(n)), Ǝ (existe) c > 0 e n 0 0 <= g(n) <= c.f(n), (qualquer) n >= n 0 6

Se dizemos que g(n) = O(n 2 ) Notação O Significa que existem constantes c e m g(n) <= c. n 2 para n >= m Exemplo: g(0) = 1 g(1) = 4 g(n) = (n+1) 2 (n+1) 2 <=c.n 2 n 2 + 2n + 1 <= c.n 2 2n + 1 <= (c-1).n 2 n (n+1) 2 2.n 2 0 1 0 1 4 2 2 9 8 3 16 18 Fazendo c = 2 e m = 3 a definição é satisfeita 7

Notação define um limite inferior para a função, por um fator constante. Escreve-se g(n) = (f(n)), se existirem constantes positivas c e n 0 para n >= n 0, o valor de g(n) é maior ou igual a c.f(n) Neste caso, diz-se que f(n) é um limite assintótico inferior para g(n). Formalmente: g(n) = (f(n)), Ǝ(existe) c > 0 e n 0 0 <= c.f(n) <= g(n), (qualquer) n >= n 0 A notação é usada para expressar o limite inferior do tempo de execução de qualquer algoritmo para resolver um problema específico Exemplo: O limite inferior para qualquer algoritmo de ordenação que utiliza comparação de chaves é (n log n). 8

Comportamento Assintótico de Funções Assim, existem duas notações principais na análise assintótica de funções: O e O(f(n)) depende do algoritmo (limite superior) (f(n)) depende do problema (limite inferior) 9

Notação A notação limita a função por fatores constantes. g(n) = (f(n)) se existirem constantes positivas c1 e c2 e n 0 tais que para n >= n 0, o valor de g(n) está sempre entre c1.f(n) e c2.f(n) inclusive. Neste caso, dizemos que f(n) é um limite assintótico firme para g(n). Formalmente: g(n) = (f(n)), Ǝ (existe) c 1 > 0 e c 2 > 0 e n 0 0 <= c 1.f(n) <= g(n) <= c 2. f(n), (qualquer) n >= n 0 10

Exemplo de uso da Notação Provem que 1/2n 2 3n = (n 2 ) Achem constantes c 1 > 0, c 2 > 0, n 0 > 0, tais que: c 1.n 2 <= 1/2n 2 3n <= c 2.n 2 para todo n >= n 0 OBS: as constantes c1 e c2 podem ser reais. 11

Classes de Comportamento Assintótico f(n) = O(1) (complexidade constante) O uso do algoritmo independe do tamanho de n. Neste caso, as instruções do programa são executadas um número fixo de vezes. f(n) = O(log n) (complexidade logaritmica) Ocorre tipicamente em algoritmos que resolvem um problema transformando-o em problemas menores. Nestes casos, o tempo de execução pode ser considerado como sendo menor que uma constante grande. Exemplos: n = 1000 -- log 2 n ~ 10; n = 10 6 log 2 n ~20. f(n) = O(n) (complexidade linear) Em geral, um pequeno trabalho é realizado sobre cada elemento de entrada. Esta é a melhor situação possível para um algoritmo que tem que processar n elementos de entrada ou produzir n elementos de saída. Cada vez que n dobra de tamanho o tempo de execução dobra. 12

Classes de Comportamento Assintótico f(n) = O(n log n) Este tempo de execução ocorre tipicamente em algoritmos resolvidos com o método dividir&conquistar. Exemplos: n = 1 milhão n log n ~20 milhões; n = 2 milhões, n log n ~ 42 milhões, pouco mais que o dobro. f(n) = O(n 2 ) (complexidade quadrática) Algoritmos desta ordem de complexidade ocorrem quando os itens são processados aos pares, em um laço dentro de outro. São úteis para resolver problemas de tamanho pequeno métodos diretos de ordenação. 13

Dividir & Conquistar Muitos algoritmos possuem uma natureza recursiva: para resolver um dado problema eles se chamam recursivamente uma ou mais vezes para tratar de subproblemas do mesmo tipo mas de tamanho menor e, Então combinam estas soluções para criar a solução original, seguindo a abordagem dividir e conquistar. Método Top-down 14

Os 3 Passos da Abordagem Dividir o problema em vários subproblemas Conquistar os subproblemas resolvendo eles recursivamente. Quando os tamanhos são pequenos resolver diretamente Combinar as soluções dos subproblemas na solução para o problema original Lembrem que o uso da recursão facilita a descrição do algoritmo e garante um mecanismo limpo para dividir o problema em 2 menores com a metade do tamanho do original. 15

MergeSort (Dividir): divida a lista L de tamanho n em duas listas de tamanho n/2 (Conquistar): Ordene as duas listas recursivamente usando o mergesort. Se a lista L tem tamanho 1 ela está ordenada. (Combinar): Intercale as duas produzindo uma lista ordenada A complexidade de tempo de MergeSort é O(n log n) 16

procedure mergesort(a,p,r); Se p < r então inicio q <- (p + q) div 2 mergesort(a,p,q) mergesort(a,q+1,r) merge(a,p,q,r) {assume que os vetores A[p..q] e A[q+1..r] estão ordenados e os intercala para formar um único array A[p..r]} fim 17

A = <5,2,4,6,1,3,2,6> 1 2 2 3 4 5 6 6 merge 2 4 5 6 1 2 3 6 merge merge 2 5 4 6 1 3 2 6 merge merge merge merge 5 2 4 6 1 3 2 6 18

Classes de Comportamento Assintótico (cont.) f(n) = O(n 3 ) (complexidade cúbica) Algoritmos desta ordem são úteis apenas para resolver pequenos problemas. f(n) = O(2 n ) (complexidade exponencial) Algoritmos desta ordem geralmente não são úteis sob o ponto de vista prático. Eles ocorrem na solução de problemas quando se usa a força bruta para resolvê-los. 19

Relação entre as ordens Onde estão n! e n n? 20

Algoritmo Exponencial Versus Polinomial Um algoritmo cuja função de complexidade é O(c n ), c > 1, é chamado de algoritmo exponencial de tempo de execução. Um algoritmo cuja função de complexidade é O(p(n)), onde p(n) é um polinômio, é chamado de algoritmo polinomial de tempo de execução. A distinção entre os dois torna-se significativa quando n cresce. Um problema é considerado intratável se ele é tão difícil que não existe um algoritmo polinomial para resolvê-lo (torres de hanoi, damas e xadrez generalizados). Um problema é considerado bem resolvido quando existe um algoritmo polinomial para resolvê-lo. São obtidos através de um entendimento mais profundo da estrutura do problema. 21

Princípios para a Análise de Algoritmos -- Prática Tempo de execução para: 1. Atribuição, leitura e escrita: O(1) Exceção linguagens que permitem atribuição direta em vetores de tamanho grande 2. Seqüência: comando de maior tempo 3. Decisão: avaliação da condição: O(1); comandos dentro: regra 2. 4. Laço: avaliação do término: O(1); comandos dentro: regra 2. 22

5. Programa com procedimentos não recursivos: o tempo de execução de cada procedimento deve ser calculado separadamente um a um. Inicia-se com aqueles que não chamam outros. A seguir são avaliados aqueles que chamam os que não chamam outros, utilizando os tempos já calculados. 6. Programa com procedimentos recursivos: para cada procedimento é associada uma função de complexidade f(n) desconhecida, onde n mede o tamanho dos argumentos para o procedimento. 23

Operações com a Notação O f(n) = O(f(n)) c. O(f(n)) = O(f(n)) se c = constante O(f(n) + O(f(n)) = O(f(n)) O(O(f(n))) = O(f(n)) O(f(n)) + O(g(n)) = O(max(f(n),g(n))) O(f(n))O(g(n)) = O(f(n)g(n)) f(n)o(g(n)) = O(f(n)g(n)) Regra da Soma Suponha 3 trechos de programas cujos tempos de execução são O(n), O(n 2 ) e O(n log n). O tempo dos 2 primeiros é O(max(n,n 2 )) que é O(n 2 ) e dos 3 é O(max(n 2, n log n) que é O(n 2 ). Regra do Produto Produto de [log n + k + O(1/n)] por [n + O(raiz(n))] = n log n 24

Fórmulas Úteis 1 1<=i<=n = n = O(n) (linearidade) i 1<=i<=n = n(n+1)/2 = O(n 2 ) (série aritmética) i 2 = [n(n+1)(2n+1)]/6 = O(n 3 ) 1<=i<=n 25

Exemplo Procedure Ordena (var A: vetor); { ordena o vetor em ordem ascendente} Var i, j, min, x: integer; Begin (1) For i:= 1 to n-1 do Begin (2) min := i; (3) for j:= i + 1 to n do (4) if A[j] < A[min] (5) then min := j; {troca A[min] e A[i]} (6) X := A[min]; (7) A[mim] := A[i]; (8) A[i] := X; End; End; 26

Análise do Programa O programa contém 2 laços, um dentro do outro. Laço mais externo: (2) a (8) Laço mais interno: (4) e (5) Começamos pelo mais interno: comando de atribuição e avaliação da condição levam tempo constante. Como não sabemos se o corpo da decisão vai ou não ser executado, considera-se o pior caso: assumir que a linha (5) sempre será executada. O tempo para incrementar o índice do laço e avaliar sua condição de termo é também O(1). O tempo para executar uma vez o laço composto por (3), (4) e (5) é O(max(1,1,1)) = O(1). Seguindo regra da soma para a notação O. 27

Como o número de iterações do laço é n-i então o tempo gasto é O(n-i. 1) = O(n i). Seguindo a regra do produto para notação O. O corpo do laço mais externo contém, além do laço interno, os comandos de atribuição nas linhas (2), (6), (7), (8). O tempo das linhas (2) a (8) é: O(max(1,(n-i),1,1,1)) = O(n-i) A linha (1) é executada n-1 vezes, o tempo total do programa é: N-1 N-1 N-1 (n i) = n. 1 - i = n.(n -1) [(n-1).(n)]/2 = n 2 n n 2 /2 n/2 i = 1 i = 1 i = 1 n 2 /2 n/2 = O(n 2 ) 28

Nro de comparações X nro de trocas Considerando o número de comparações como a mais relevante (4): n 2 /2 n/2 comparações Considerando o número de trocas (6), (7), (8) a mais relevante: 3(n-1) trocas. 29

Procedimento Recursivo para calcular n! function fat(n: integer): integer; Begin (1) If n <= 1 (2) then fat := 1 { escape da recursão } (3) Else fat := n * fat (n-1) End; Seja T(n) o tempo de execução para fat(n) (1)-> O(1) (2)-> O(1) (3)-> O(1) + T(n-1) Assumindo custos de T(n) = 1 + T(n 1) multiplicações T(n-1) = 1 + T(n-2) T(1) = 0 pois não multiplica... T(2) = 1 + T(1) T(n) = 1 + T(n 1) n > = 2 T(n) = 1 + 1 + 1+...+1 + T(1) n 1 vezes Método da Iteração: expande a recorrência e expressa ela como uma 30 soma. Relação de Recorrência:

Procedimento não recursivo para fatorial function fat (n : integer): integer; var f, i: integer; begin f:= 1; for i:= 2 to n do f:= f*i; fat := f End; F(n) -> custo de multiplicações F(1) = 0 F(n) = n - 1 31

Resolvendo Recorrências Quando um algoritmo contém uma chamada recursiva a ele mesmo, seu tempo de execução pode ser expresso como uma recorrência. Existem 3 métodos (Cormen et all, 1999): Método Mestre: Fornece 3 casos para resolver T(n) =at(n/b) + f(n), a>=1; b>1 Método da Substituição: O objetivo é encontrar uma função (chute) tal que T(n) = O(f(n)) e provar por indução em n. Método da Iteração: Expande a recorrência e expressa ela como soma. Método mais utilizado. 32