22

Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Embed Size (px)

Citation preview

Page 1: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou
Page 2: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

IntroduçãoAnalisar um algoritmo significa prever os

recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou tempo.

Podemos analisar • O tempo de processamento em função de seus dados de

entrada;• A memória total utilizada pelo programa;• O número de linhas do código do programa;• Se o programa chega corretamente ao resultado;• Se o programa é fácil de entender e de ser alterado;• Se os erros causados por dados incorretos ou

inesperados são tratados corretamente.

Page 3: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Entretanto uma análise detalhada da performance de um algoritmo, que leve em consideração todos esses fatores, é muito complicada e não muito significativa. De todos estes fatores tempo é o recurso mais freqüentemente medido.

Em geral pela análise podemos indicar se um algoritmo é mais eficiente que o outro.

Esta análise pode ser feita a partir de dois processos: pelo método empírico e pelo método analítico.

Usar o método empírico possui os seguintes problemas:Os resultados são dependentes do compiladorOs resultados são dependentes do hardwareQuando grandes quantidades de memória são usadas os

resultados podem depender deste aspectoApesar dos problemas acima o método empírico é

útil quando temos vários algoritmos distintos, que resolvem o mesmo problema, de mesma ordem de grandeza.

Page 4: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

No método analítico procura-se determinar uma expressão que nos forneça o tempo de execução em função da quantidade de dados processados, isto é:

Tempo = f(N)A complexidade de um algoritmo é o termo

normalmente utilizado para se fazer referência à sua eficiência

Para se encontrar a expressão que nos dá o tempo de execução de um algoritmo teremos que determinar a quantidade de operações que serão executadas para um conjunto de dados de tamanho N.

Como exemplo, vamos determinar o tempo de execução para o cálculo do somatório de uma série aritmética simples:

Page 5: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

1 I    := 1; 2 Soma := 0; 3 while I <= N do begin 4    Soma := Soma + I; 5    I    := I + 1; 6 end;

Na análise do programa acima vamos considerar que os tempos necessários para realizar as operações de atribuição, comparação e adição são dados por T:=, T<= e T+, respectivamente.

Page 6: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Na análise anterior os tempos das operações depende dos fatores listados anteriormente. Dessa forma, fica bastante difícil comparar a eficiência de dois algoritmos usando esse mecanismo uma vez que teremos que especificar também o ambiente em que a medição foi feita.

Para simplificar iremos usar um computador idealizado que executaria qualquer instrução em um mesmo tempo T.

Em nosso modelo também não tentaremos modelar a hierarquia de memória.

Esta análise convencional permite previsões excelentes do desempenho em máquinas reais.

O efeito de tal simplificação resulta em que não precisamos mais considerar as operações separadamente. Dessa forma, para determinar o tempo de processamento de um programa basta simplesmente contar o número total de operações

Page 7: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Análise dos Tempos de ProcessamentoConsideremos o problema de se determinar

o maior valor de um vetor fazendo uma busca seqüencial no vetor:

public class Max{ public static int max(int v[ ], int n){ int max = v[0]; for (int i = 1; i<n; i++) if (max < v[i]) max = v[i]; return max; }}

Page 8: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Tempos de processamento do melhor caso, do pior caso e do caso médio

Consideremos o problema de se determinar o maior valor de um vetor fazendo uma busca seqüencial no vetor:

1 max = A[0]; 2 i = 0; 3 while (i < N) { 4    if (A[i] > max) 5     max = A[i]; 6 i = i + 1;    }  

Page 9: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Agora surge um problema: quantas vezes a linha 5 será executada? Neste caso não sabemos pois depende dos valores existentes no vetor. O que fazer então? Três estratégias são adotadas:

• Determinar o tempo do pior caso• Determinar o tempo do melhor caso• Determinar o tempo do caso médio

Page 10: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

O pior caso: Ordem crescente. Linha 5 é executada em todas as iterações do laço. Dessa forma, o tempo de processamento para o pior caso é dado por:

T(N) = 5N + 3  O melhor caso: Ordem decrescente. Linha 5 nunca é

executada. O tempo de processamento será então:T(N) = 4N + 3

O cálculo do tempo médio de processamento exige o prévio conhecimento da distribuição de probabilidades das diferentes entradas. Na maioria dos casos essa distribuição é desconhecida e freqüentemente é de tratamento matemático complexo.

Como a análise do pior caso nos dá um limite superior do tempo de processamento, ela é a mais utilizada.

Page 11: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Exercício

Considere o seguinte algoritmo...1 - soma = 0;2 - for(x = 0; x < N; x++)3 - {4 - if (vetor[x] % 2 == 0)5 - soma = soma + vetor[x];6 - }7 - media = soma / N;

Page 12: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Exercício 2Calcule, usando a simplificação vista, a

complexidade do seguinte algoritmo 1 - for(x = 0; x < N-1; X++) 2 - for( y = 0; y < N; y++) 3 - if(vetor[x] > vetor[y]) 4 - { 5 - aux = vetor[x]; 6 - vetor[x] = vetor[y]; 7 - vetor[y] = aux; 8 - }

Page 13: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Notação OQuando estamos analisando a ordem de

crescimento de um algoritmo normalmente estamos interessados em se ter uma idéia de como o método se comporta quando alteramos o valor de N. Para isso precisamos apenas analisar o termo de maior valor da expressão, ou seja o termo que cresce mais rápido.

Exemplo: T(N) = N2+2NO termo representativo da expressão nos

dá a sua ordem, sendo representado pela notação O, a qual é escrita colocando-se a letra O e, entre parênteses, o termo representativo da expressão.

Page 14: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Assim, o algoritmo acima seria expresso na notação O como sendo O(N2), que se lê da seguinte forma: o algoritmo tem complexidade O(N2) ou sua complexidade é de ordem N2.

A notação O pode ser derivada a partir de T(N) da seguinte maneira:

• Fazer o coeficiente de cada termo igual a um;

• Tomar o maior termo da função como sendo a ordem do algoritmo, descartando os termos restantes.

Page 15: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Normalmente dividem-se as complexidades dos algoritmos em sete categorias como mostradas na tabela abaixo:

Page 16: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Gráficos de cada complexidade em função de N

Exemplo:Exemplo:Obtenha a notação Obtenha a notação O O para: para:

Page 17: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Regras Para a Notação O

A seguir apresentamos algumas regras simples para a determinação da complexidade do tempo de processamento de algumas composições básicas de comandos em um programa.

Regra 1: Tempo constanteA ordem de um algoritmo cujo tempo independe de N é

constante e igual a O(1).

Regra 2: Composição seqüencialO tempo de processamento para o pior caso de uma

seqüência de comandos, tais como:S1;S2;...S3;é igual à ordem do maior tempo entre todos os comandos.

Page 18: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Regras Para a Notação O Regra 3: Iteração

O tempo de processamento para o pior caso de um laço do tipo:

for I := 1 to N   S;

é igual ao tempo de execução de S multiplicado pelo número de vezes que ele será executado no pior caso, isto é, a ordem é O(N x Ts(N)), onde Ts(N) é o tempo máximo de execução de S.

Regra 4: Execução condicionalO tempo de processamento para o pior caso de um comando if-then-else

if S1 then  S2else  S3;é igual ao maior tempo de execução entre os comandos S2 e S3.

Page 19: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

ExemploSeja o problema para calcular a série de somas

S1, S2, ..., Sn, obtidas por:

cujo algoritmo é:1  J := 1;2  while J <= N do begin3     S[J] := 0;4     I    := 1;5     while I <= J do begin6        S[J] := S[J] + A[I];7        I := I + 1;8     end;9     J := J + 1;10 end;

Page 20: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Vejamos o cálculo da ordem do algoritmo:

Page 21: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

Exercícios1) Cada uma das seguintes fórmulas

representa o número de operações de determinado algoritmo. Exprimir cada uma delas usando a notação O:a) n2 + 5n b) 3n2 + 5nc) (n + 7)(n – 2) d) 100n + 5e) 6Log2N + 9N

f) 3N4 + NLog2Ng) 5N2 + N3/2

Page 22: Introdução Analisar um algoritmo significa prever os recursos que o algoritmo necessitará. Podem ser recursos de memória, largura de banda, hardware ou

2) Escrever um trecho de programa contendo um laço para calcular a soma de todos os números inteiros de 1 a n. Fazer uma análise do tempo requerido, contando o número de somas e atribuições efetuadas e a seguir concluir qual a ordem do algoritmo.

3) Calcular a complexidade do seguinte trecho de programa:

I := 1;while I <= N do begin   J := 1;   while J <= N do begin      K := 1;      while K <= N do begin         Writeln(I, J, K);         K := K + 1;      end;      J := J + 1;   end;   I := I + 1;end;