Você está na página 1de 23

Análise da complexidade

de algoritmos iterativos e
recursivos
Agenda
1. Revisão sobre análise de complexidade de algoritmos
2. Conceituação de algoritmos iterativos
3. Análise da complexidade de algoritmos iterativos e principais exemplos
4. Conceituação de algoritmos recursivos
5. Análise da complexidade de algoritmos recursivos e principais exemplos
6. Conclusões
Revisão sobre análise de
complexidade de
algoritmos
Análise de Algoritmos  determinar a complexidade (custo)
◦ Comparar algoritmos
◦ Determinar se um algoritmo é “ótimo”

Custo de um algoritmo:
Revisão ◦ Tempo (número de passos)  depende do input (n)
◦ Espaço (memória)
Medida do custo por meio de um modelo matemático
◦ Considerar apenas as operações mais significativas
t = F(n)

arrayMax(A, n):
Revisão //Entrada: array A com n(>=1) elementos inteiros
//Saida: o maior elemento em A

tmpMax <- A[0]


for i<-1 to n-1 do
if tmpMax < A[i] then
tmpMax <- A[i]
return tmpMax
código custo vezes
tmpMax <- A[0] c1 1
for i <- 1 to n-1 do c2 n
if tmpMax < A[i] then c3 n-1

Revisão tmpMax <- A[i]


return tmpMax
c4
c5
n-1
1

T∗(n) = c1*1+ c2*n + c3*(n-1) + c5 * 1 (melhor caso)


T∗(n) = c1+ n*c2 + n*c3 – c3 + c5

se considerarmos os custos iguais, teremos:

T∗(n) = c+ n*c + n*c – c + c = 2n*c + c


Para c =1:
Custo para o melhor caso = 2n + 1
código custo vezes
tmpMax <- A[0] c1 1
for i <- 1 to n-1 do c2 n
if tmpMax < A[i] then c3 n-1

Revisão tmpMax <- A[i]


return tmpMax
c4
c5
n-1
1

T∗(n) = c1*1+ c2*n + c3*(n-1) + c4*(n-1) + c5 * 1 (pior caso)


T∗(n) = c1+ n*c2 + n*c3 – c3 + n*c4 – c4 + c5
se considerarmos os custos iguais, teremos:
T∗(n) = c+ n*c + n*c – c + n*c – c + c = 3n*c
Para c =1, o Custo para o pior caso = 3n
t(l): custo médio
T∗(n) ≤ t(I) ≤ T*(n)
2n+1 ≤ t(I) ≤ 3n
Comportamento assintótico  (n → ∞)
◦ Notação Big-O  limite superior de complexidade
◦ Não contam os termos de baixa ordem, e as constantes.
◦ Exemplos

Revisão

Fonte: https://stackoverflow.com/questions/4317414/polynomial-time-and-exponential-time
Algoritmos iterativos
Algoritmos iterativos
Utilizam estruturas de repetição de passos (iteração), através de laços de repetição tais como:
◦ For
◦ While
◦ Do...while

for (int i = 0; i<10; i++){ while(i<10){ do{


... i++; ...
} .... }while (i<10);
}
Análise da complexidade de algoritmos
iterativos
Análise da complexidade de algoritmos
iterativos
Regras para o cálculo:
◦ Laços: tempo de execução de um laço = soma dos tempos de todas as instruções dentro dele * número
de iterações.
◦ Laços aninhados: tempo total de execução = tempo da instrução * produto dos tamanhos de todos os
laços.

Exemplo: O(n2)

para i de 1 até n faça


para j de 1 até n faça
k <- k + 1;
fim para
fim para
Análise da complexidade de algoritmos
iterativos
Regras para o cálculo:
◦ Instruções Consecutivas: são somadas, ignorando os termos de ordem menor

Exemplo: O(n) + O(n2) = O(n2)

para i de 1 até n faça


a[i] <- 0;
fim para
para i de 1 até n faça
para j de 1 até n faça
a[i] <- a[j] + k + 1;
fim para
fim para
Procedure Verifica_Item(Lista: TipoLista; x: TipoItem; pos: integer);
Var i: integer;
Begin
i:=1; O(1)
achou := false;
while (i <= Lista.Tamanho) and not achou do O(N)
if Lista.Item[i] = x then
achou := true;
O(1)
if achou then
pos := i
else
for i:= Lista.Tamanho +1 to MaxTam; O(N)

Lista.Item[i] := x; O(1)

f(N) = O(7 * O(1) + 2*O(N)) = O(O(1) + (O(N)) = O(N)


Algoritmos recursivos
Algoritmos recursivos
Também usam iteração, mas repetindo-se a si mesmo
Cada instância do problema contém uma instância menor do mesmo problema

int multiplicacao (int m, int n){


if(n==0)
return 0;
else
return (m+multiplicacao(m,n-1));
}
Análise da complexidade de algoritmos
recursivos
Fatorial(n) No caso da recursividade,
SE n == 0 ENTÃO depende da quantidade de
iterações que se pode chegar
retorne 1;
Ex.: se eu quiser saber os N
SENÃO primeiros termos de um
retorne Fatorial(n - 1) * n; fatorial, a complexidade é N
FIM SE

Considera-se f(n) = T(n) = T(n-1) + constante


f(n) é a simplificação da Relação de Recorrência: equação ou
desigualdade que descreve uma função em termos de seu valor em
entradas menores
Análise de recorrência
T(n) = T(n - 1) + 1 para n > 0
T(n) = 1 para n = 0

T(n) = T(n-1)+1 = T(n-2)+1+1 = T(n-3)+1+1+1 = · · · = T(n-n)+n = T(0)+n

Substituindo-se : T(n) = 1 + n

f(n) = T(n) = n  O(n)


Análise da complexidade de algoritmos
recursivos
O exemplo anterior pode ser "iterativisado" de forma extremamente simples com apenas um laço para-faça (for):

inteiro FatorialIterativo(inteiro n)
inteiro i, fatorial;
início
fatorial <- 1;
para i de 2 até n faça
fatorial <- fatorial * i;
fim para
retorne fatorial;
fim

Qual a complexidade agora?


O(n)
A complexidade de espaço é O(1), enquanto que no fatorial original é O(n) devido a pilha de execução  problema da
recursão
Análise da complexidade de algoritmos
recursivos
O caso dos números de Fibonacci abaixo não é tão simples e requer a resolução de uma relação de recorrência:
inteiro Fibonacci(inteiro n)
início
se n <= 1 então
retorne 1
senão
retorne (Fibonacci(n-1) + Fibonacci(n-2));
fim se
fim

 Para n >= 2 temos um tempo de execução: T(n) = [T(n-1) + 1] + [T(n-2)+1]


T(1) e T(0)= 1
Logo…. T(n) = [T(n-n+1) +n+1] + [T(n-n) + n]
= [T(1)+ n+1] + [T(0)+n] =
= [2+n] + [1+n]
= 2n + 3  O(n)
Conclusões
A análise de complexidade de algoritmos é importante para compreender a eficiência e o custo
dos processamentos
Algoritmos iterativos e recursivos utilizam-se de repetição para realizar seus cálculos, porém de
forma distinta
Para se analisar o comportamento assintótico desses algoritmos é necessário ter prática e, por
vezes, realizar cálculos individuais do custo de cada operação
Algoritmos recursivos podem ser implementados de forma iterativa, mantendo a complexidade
com relação ao tempo, mas reduzindo-a com relação ao espaço
Atividade extra classe

Fazer upload das respostas da atividade na Tarefa do Google Classroom


Dúvidas?