análise de algoritmos · • típico em algoritmos que quebram um problema em outros menores,...

32
Análise de Algoritmos Parte 3 Prof. Túlio Toffolo http://www.toffolo.com.br BCC202 – Aula 06 Algoritmos e Estruturas de Dados I

Upload: others

Post on 19-Aug-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Análise de Algoritmos Parte 3 Prof. Túlio Toffolo http://www.toffolo.com.br

BCC202 – Aula 06

Algoritmos e Estruturas de Dados I

Page 2: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Como escolher o algoritmo mais adequado para uma situação?

(continuação)

Page 3: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Exercício da última aula teórica

•  Obtenha a função de complexidade f(n) dos algoritmos abaixo. Considere apenas as operações envolvendo as variáveis x e y. Para cada algoritmo, responda:

•  Qual o valor da variável x ao final da execução do algoritmo?

•  O algoritmo é O(n2)? É Ω(n3)?

•  O algoritmo é Ө(n3)?

void exercicio1(int n) { int i, j, x, y; x = y = 0; for (i = 1; i <= n; i++) { for (j = i; j <= n; j++) x = x + 1; for (j = 1; j < i; j++) y = y + 1; }}

void exercicio2(int n) { int i, j, k, x; x = 0; for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) for (k = 1; k <= j; k++) x = x + j + k; x = i;}

Page 4: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Perguntas?

Page 5: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Comportamento Assintótico de Funções

•  Nas aulas passadas aprendemos:

•  Como calcular a função de complexidade f(n).

Ø  Melhor caso x Caso médio x Pior caso

Ø  Qual a influência desta função em algoritmos aplicados sobre problemas de tamanho pequeno?

Ø  E sobre problemas grandes?

Ø  Estuda-se o comportamento assintótico das funções de custo. O que isto significa?

5

Page 6: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

void MaxMin1(int* A, int n, int* pMax, int* pMin) { int i; *pMax = A[0]; *pMin = A[0]; for (i = 1; i < n; i++) { if (A[i] > *pMax) *pMax = A[i]; if (A[i] < *pMin) *pMin = A[i]; } }

2*(n-1)

Qual a ordem de complexidade?

6

Page 7: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

void MaxMin2(int* A, int n, int* pMax, int* pMin) { int i; *pMax = A[0]; *pMin = A[0]; for (i = 1; i < n; i++) { if (A[i] > *pMax) *pMax = A[i]; else if (A[i] < *pMin) *pMin = A[i]; } }

2*(n-1)

Qual a ordem de complexidade?

7

Page 8: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Comportamento Assintótico de Funções

•  Nas aulas passadas também aprendemos:

•  Comportamento assintótico das função de complexidade f(n).

Ø  Dominação Assintótica

Ø  Notação O

Ø  Notação Ω e Notação Ө.

8

Page 9: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Operações com a Notação O

9

Page 10: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Dominação Assintótica

•  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)|.

10

Page 11: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Notação O

•  O valor da constante m mostrado é o menor valor possível, mas qualquer valor maior também é válido.

•  Definição: uma função g(n) é O(f(n)) se existem duas constantes positivas c e m tais que g(n) ≤ c f(n), para todo n ≥ m.

11

Page 12: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Notação Ω

•  Especifica um limite inferior para g(n).

•  Definição: Uma função g(n) é Ω(f(n)) se:

Ø  Existem duas constantes positivas c e m tais que, para n ≥ m, temos |g(n)| ≥ c|f(n)|.

12

Page 13: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Notação Ө

•  Exemplo gráfico de dominação assintótica que ilustra a notação Ө.

•  Especifica um limite assintótico firme para g(n).

Ø  Para ser Ө(f(n)), uma função deve ser ao mesmo tempo O(f(n)) e Ω(f(n)).

13

Page 14: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Notação Ө

Ø  Para mostrar que g(n) = 3n3 + 2n2 é Ω(n3) basta fazer: c = 1, e então 3n3 + 2n2 ≥ n3 para n ≥ 0.

Ø  Seja g(n) = n2 para n par (n ≥ 0) g(n) = n para n ímpar (n ≥ 1).

Neste caso g(n) poderá ser:

Ω(n2), se considerarmos apenas entradas pares

Ω(n), se considerarmos apenas entradas ímpares

Se considerarmos qualquer entrada possível, então g(n) é Ω(n)

14

Page 15: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Perguntas....

•  n é O(n log n)? Esta afirmação é útil?

•  n3 é Ω(n)? Esta afirmação é útil?

•  n é O(n)?

•  n é Ω(n)?

•  n é Ө(n)?

•  n é Ө(n log n)?

15

Page 16: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Comparação de Programas

•  Um programa com tempo de execução O(n) é melhor que outro com tempo O(n2).

•  Porém, as constantes de proporcionalidade podem alterar esta consideração.

•  Exemplo: um programa leva 100n unidades de tempo para ser executado e outro leva 2n2. Qual dos dois programas é melhor?

•  Depende do tamanho do problema.

•  Para n < 50, o programa com tempo 2n2 é melhor do que o que possui tempo 100n.

16

Page 17: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

•  f(n) = O(1) •  Algoritmos de complexidade O(1) são ditos de complexidade

constante.

•  Uso do algoritmo independe de n.

•  As instruções do algoritmo são executadas um número fixo de vezes.

Principais Classes de Problemas

17

Page 18: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

•  f(n) = O(log n) •  Um algoritmo de complexidade O(log n) é dito ter complexidade

logarítmica.

•  Típico em algoritmos que transformam um problema em outros menores.

•  Pode-se considerar o tempo de execução como menor que uma constante grande.

•  Quando n é mil, log2n 10, quando n é 1 milhão, log2n 20.

•  Para dobrar log n temos que elever n ao quadrado….

•  A base do logaritmo muda pouco estes valores: quando n é 1 milhão, o log2n é 20 e o log10n é 6.

Principais Classes de Problemas

18

Page 19: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Principais Classes de Problemas

•  f(n) = O(n) •  Um algoritmo de complexidade O(n) é dito ter complexidade

linear

•  Em geral, um pequeno trabalho é realizado sobre cada elemento de entrada

•  É a melhor situação possível para um algoritmo que tem de processar/produzir n elementos de entrada/saída.

•  Cada vez que n dobra de tamanho, o tempo de execução dobra.

19

Page 20: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

•  f(n) = O(n log n) •  Típico em algoritmos que quebram um problema em outros

menores, resolvem cada um deles independentemente e juntando as soluções depois.

•  Quando n é 1 milhão, nlog2n é cerca de 20 milhões.

•  Quando n é 2 milhões, nlog2n é cerca de 42 milhões, pouco mais do que o dobro.

Principais Classes de Problemas

20

Page 21: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Principais Classes de Problemas

•  f(n) = O(n2) •  Um algoritmo de complexidade O(n2) é dito ter complexidade

quadrática.

•  Ocorrem quando os itens de dados são processados aos pares, muitas vezes em um anel dentro de outro.

•  Quando n é mil, o número de operações é da ordem de 1 milhão.

•  Sempre que n dobra, o tempo de execução é multiplicado por 4.

•  Úteis para resolver problemas de tamanhos relativamente pequenos.

21

Page 22: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Principais Classes de Problemas

•  f(n) = O(n3) •  Um algoritmo de complexidade O(n3) é dito ter complexidade

cúbica.

•  Úteis apenas para resolver pequenos problemas.

•  Quando n é 100, o número de operações é da ordem de 1 milhão.

•  Sempre que n dobra, o tempo de execução fica multiplicado por 8.

22

Page 23: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Principais Classes de Problemas

•  f(n) = O(2n) •  Um algoritmo de complexidade O(2n) é dito ter complexidade

exponencial.

•  Geralmente não são úteis sob o ponto de vista prático.

•  Ocorrem na solução de problemas quando se usa força bruta para resolvê-los.

•  Quando n é 20, o tempo de execução é cerca de 1 milhão. Quando n dobra, o tempo fica elevado ao quadrado.

23

Page 24: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Principais Classes de Problemas

•  f(n) = O(n!) •  Um algoritmo de complexidade O(n!) é dito ter complexidade

exponencial, apesar de O(n!) ter comportamento muito pior do que O(2n).

•  Geralmente ocorrem quando se usa força bruta para resolver o problema.

•  n = 20 → 20! = 2.432.902.008.176.640.000, um número com 19 dígitos.

•  n = 40 → um número com 48 dígitos.

24

Page 25: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

25

Page 26: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

26

Page 27: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Algoritmo Polinomial

•  Algoritmo exponencial no tempo de execução tem função de complexidade O(cn); c > 1.

•  Algoritmo polinomial no tempo de execução tem função de complexidade O(p(n)), onde p(n) é um polinômio.

•  A distinção entre estes dois tipos de algoritmos torna-se significativa quando o tamanho do problema a ser resolvido cresce.

•  Por isso, os algoritmos polinomiais são muito mais úteis na prática do que os exponenciais.

27

Page 28: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Quem vê, entende...

Mas é quem faz que aprende!

28

Page 29: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Exercício 1

•  Indique se as afirmativas a seguir são verdadeiras ou falsas e justifique a sua resposta

•  É melhor um algoritmo que requer 2n passos do que um que requer 10n10 passos.

•  2n+1 = O(2n).

•  f(n) = O(u(n)) e g(n) = O(v(n)) => f(n) + g(n) = O(u(n) + v(n))

•  f(n) = O(u(n)) e g(n) = O(v(n)) => f(n) - g(n) = O(u(n) - v(n))

29

Page 30: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Exercício 2

// Considere A, B e C vetores globaisvoid p1 (int n) { int i, j, k; for (i=0; i<n; i++) for (j=0; j<n; j++) { C[i][j]=0; for (k=n-1; k>=0; k--) C[i][j]=C[i][j]+A[i][k]*B[k][j]; }}

30

•  Calcule a função de complexidade e a complexidade assintótica de p1

Page 31: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Exercício 3

void p2 (int n){ int i, j, x, y; x = y = 0; for (i=1; i<=n; i++) { for (j=i; j<=n; j++) x = x + 1; for (j=1; j<i; j++) y = y + 1; }}

31

void p3 (int n){ int i, j, x, y; x = y = 0; for (i=1; i<=n; i++) { for (j=i; j<=n; j++) x = x + 1; }}

•  Calcule a função de complexidade e a complexidade assintótica de p2 e p3. Qual é mais rápido?

Page 32: Análise de Algoritmos · • Típico em algoritmos que quebram um problema em outros menores, resolvem cada um deles independentemente e juntando as soluções depois. • Quando

Perguntas?