Complexidade:


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