Dado um problema e um algoritmo de solução queremos saber quantas operações elementares são necessárias para aplicar o algoritmo a uma instancia do problema de tamanho n, c(n).
As operações elementares que contamos são uma proxi para o tempo de execução do algoritmo e, dependendo da conveniência, podem ser por exemplo: Operações aritméticas, operações de leitura ou escrita de dados, operações de acesso a dados na memória, etc.
Problema 1: computar xn, x em R , n em N.
Apresentaremos 2 algoritmos básicos, o óbvio e o divida-e-conquiste,
cada qual em uma versão recursiva e uma versão iterativa.
Na versao recursiva a funcao chama a si mesma, com um argumento (x,m) , m<n.
No algoritmo óbvio, m = n – 1, enquanto no divida-e-conquiste m = floor(n/2).
Na versão iterativa os cálculos efetuados são praticamente os
mesmos, mas não usamos o recurso de chamar a função recursivamente.
function z = power1(x,n)
%*** versao recursiva ***
%*** do algoritmo obvio ***
if ( n == 0 )
z = 1;
else
z = x*power1(x,n-1);
end
%**************************
function z = power2(x,n)
%*** versao iterativa ***
%*** do algoritmo obvio ***
if ( n == 0 )
z = 1;
else
z = 1;
k = n;
while ( k >= 1 )
z = x*z;
k = k-1;
end %while
end %if
%**************************
function z = power3(x,n)
%*** versao recursiva do algoritmo ***
%*** estrategia divida e conquiste ***
if (n == 0)
z = 1;
else
q = floor( n/2 ); %quociente
r = n – 2*q; %resto = n mod 2
y = power3(x,q);
z = y*y;
if ( r == 1 ) %n impar
z = x*z;
end
end
%************************************
function z = power4(x,n)
%*** versao iterativa do algoritmo ***
%*** estrategia divida e conquiste ***
k=n;
z=1;
y=x;
while ( k > 0 )
q = floor( k/2 ); %quociente
r = k – 2*q; %resto = k mod 2
if ( r == 1 ) %k impar
z=y*z;
end %if
y=y*y;
k=q;
end %while
%*************************************
Tomando o produto como Operação Elementar, é fácil verificar que o número de OE’s executadas em cada algoritmo é:
C1(n) = C2(n) = n e
C3(n) = C4(n) <= 2*log2(n)
Muitas vezes estamos interessados apenas em saber um limite superior para a complexidade de uma algoritmo, expresso em uma forma simples.
Se, dada uma funcao f(n) , existem constantes K e N | n >= N => f(n) <= K*g(n), então dizemos que “f é da ordem de g” , ou f=O(g).
Assim, dizemos que a complexidade dos dois primeiros algoritmos é da ordem de n, enquanto a complexidade dos dois ultimos é da ordem de log2(n) .