Você está na página 1de 29

Aula 6 Recursividade

David Menotti
Algoritmos e Estruturas de Dados I
DECOM UFOP

Conceito de Recursividade

Fundamental em Matemtica e Cincia da


Computao

Exemplos

Um programa recursivo um programa que


chama a si mesmo
Uma funo recursiva definida em termos dela
mesma
Nmeros naturais, Funo fatorial, rvore

Conceito poderoso

Define conjuntos infinitos com comandos finitos

Renato Ferreira

David Menotti

Algoritmos e Estrutura

Recursividade

A recursividade uma estratgia que pode ser utilizada


sempre que o clculo de uma funo para o valor n,
pode ser descrita a partir do clculo desta mesma
funo para o termo anterior (n-1).
Exemplo Funo fatorial:
n! = n * (n-1) * (n-2) * (n-3) *....* 1
(n-1)! = (n-1) * (n-2) * (n-3) *....* 1
logo:
n! = n * (n-1)!

David Menotti

Algoritmos e Estrutura

Recursividade

Definio: dentro do corpo de uma funo,


chamar novamente a prpria funo

recurso direta: a funo A chama a prpria


funo A
recurso indireta: a funo A chama uma funo
B que, por sua vez, chama A

David Menotti

Algoritmos e Estrutura

Condio de parada

Nenhum programa nem funo pode ser


exclusivamente definido por si

Condio de parada

Um programa seria um loop infinito


Uma funo teria definio circular
Permite que o procedimento pare de se executar
F(x) > 0 onde x decrescente

Objetivo

Estudar recursividade como ferramenta prtica!

Renato Ferreira

David Menotti

Algoritmos e Estrutura

Recursividade

Para cada chamada de uma funo,


recursiva ou no, os parmetros e as
variveis locais so empilhados na pilha de
execuo.

David Menotti

Algoritmos e Estrutura

Execuo

Internamente, quando qualquer chamada de funo


feita dentro de um programa, criado um
Registro de Ativao na Pilha de Execuo do
programa
O registro de ativao armazena os parmetros e
variveis locais da funo bem como o ponto de
retorno no programa ou subprograma que chamou
essa funo.
Ao final da execuo dessa funo, o registro
desempilhado e a execuo volta ao subprograma
que chamou a funo

David Menotti

Algoritmos e Estrutura

Exemplo
Fat (int n) {
if (n<=0)
return 1;
else
return n * Fat(n-1);
}
Main() {
int f;
f = fat(5);
printf(%d,f);
}
David Menotti

Algoritmos e Estrutura

Complexidade

A complexidade de tempo do fatorial recursivo O(n).


(Em breve iremos ver a maneira de calcular isso
usando equaes de recorrncia)

Mas a complexidade de espao tambm O(n),


devido a pilha de execuo

Ja no fatorial no recursivo
a complexidade de
espao O(1)

David Menotti

Fat (int n) {
int f;
f = 1;
while(n > 0){
f = f * n;
n = n 1;
}
return f;
}
Algoritmos e Estrutura

Recursividade

Portanto, a recursividade nem sempre a


melhor soluo, mesmo quando a definio
matemtica do problema feita em termos
recursivos

David Menotti

Algoritmos e Estrutura

Fibonacci

Outro exemplo: Srie de Fibonacci:

Fn = Fn-1 + Fn-2

n > 2,

F0 = F1 = 1

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89...

Fib(int n) {
if (n<2)
return 1;
else
return Fib(n-1) + Fib(n-2);
}
David Menotti

Algoritmos e Estrutura

Anlise da funo
Fibonacci
Ineficincia em Fibonacci

Termos Fn-1 e Fn-2 so computados


independentemente
Nmero de chamadas recursivas = nmero de
Fibonacci!
Custo para clculo de Fn
O(n) onde = (1 + 5)/2 = 1,61803...
Golden ratio
Exponencial!!!

David Menotti

Algoritmos e Estrutura

Fibonacci no recursivo
int FibIter(int n) {
int i, k, F;

i = 1; F = 0;
for (k = 1; k <= n; k++) {
F += i;
i = F - i;
}
return F;

Complexidade: O(n)
Concluso: no usar recursividade
cegamente!

David Menotti

Algoritmos e Estrutura

Quando vale a pena usar


recursividade

Recursividade vale a pena para Algoritmos


complexos, cuja a implementao iterativa
complexa e normalmente requer o uso
explcito de uma pilha

Dividir para Conquistar (Ex. Quicksort)


Caminhamento em rvores (pesquisa,
backtracking)

David Menotti

Algoritmos e Estrutura

Dividir para Conquistar

Duas chamadas recursivas

Muito usado na prtica

Soluo eficiente de problemas


Decomposio

No se reduz trivialmente como fatorial

Cada uma resolvendo a metade do problema

Duas chamadas recursivas

No produz recomputao excessiva como


fibonacci

Pores diferentes do problema

David Menotti

Algoritmos e Estrutura

Outros exemplos de
recursividade
void estrela(int x,int y, int r)
{
if ( r > 0 )
{
estrela(x-r, y+r, r div 2);
estrela(x+r, y+r, r div 2);
estrela(x-r, y-r, r div 2);
estrela(x+r, y-r, r div 2);
box(x, y, r);
}
}

David Menotti

Algoritmos e Estrutura

Exemplo simples: rgua


int regua(int l,int r,int h)
{
int m;
if ( h > 0 )
{
m = (l + r) / 2;
marca(m, h);
regua(l, m, h 1);
regua(m, r, h 1);
}
}

David Menotti

Algoritmos e Estrutura

Execuo: rgua
regua(0, 8, 3)
marca(4, 3)
regua(0, 4, 2)
marca(2, 2)
regua(0, 2, 1)
marca(1, 1)
regua(0, 1, 0)
regua(1, 2, 0)
regua(2, 4, 1)
marca(3, 1)
regua(2, 3, 0)
regua(3, 4, 0)
regua(4, 8, 2)
marca(6, 2)
regua(4, 6, 1)
marca(5, 1)
regua(4, 5, 0)
regua(5, 6, 0)
regua(6, 8, 1)
marca(7, 1)
regua(6, 7, 0)
regua(7, 8, 0)
David Menotti

Algoritmos e Estrutura

Anlise de Complexidade
O
Define-se uma funo de complexidade f(n)
desconhecida

n mede o tamanho dos argumentos para o


procedimento em questo

Identifica-se a equao de recorrncia T(n):

Especifica-se T(n) como uma funo dos termos


anteriores
Especifica-se a condio de parada (e.g. T(1))

David Menotti

Algoritmos e Estrutura

Anlise da Funo Fatorial

Qual a equao de recorrncia que descreve


a complexidade da funo fatorial?
T(n) = 1 + T(n-1)
T(1) = 1
T(n) = 1 + T(n-1)
T(n-1) = 1 + T(n-2)
T(n-2) = 1 + T(n-3)
...
T(2) = 1 + T(1)

David Menotti

Algoritmos e Estrutura

Anlise de Funes
Recursivas
Alm da anlise de custo do tempo, deve-se
analisar tambm o custo de espao

Qual a complexidade de espao da funo


fatorial (qual o tamanho da pilha de
execuo)?

David Menotti

Algoritmos e Estrutura

Anlise da Funo
Recursiva
Considere a seguinte funo:

Pesquisa(n)
{
(1) if (n <= 1)
(2)
inspecione elemento e termine;
else
{
(3)
para cada um dos n elementos inspecione elemento;
(4)
Pesquisa(n/3) ;
}

}
David Menotti

Algoritmos e Estrutura

Anlise da Funo
Recursiva
Qual a equao de recorrncia?
T(n) = n + T(n/3)
T(1) = 1

Resolva a equao de recorrncia

Dicas:

Pode fazer a simplificao de n ser sempre


divisvel por 3
Somatrio de uma PG finita: (a0 rn)/(1-r)

David Menotti

Algoritmos e Estrutura

Resolvendo a equao

Substitui-se os termos T(k), k < n, at que todos os termos


T(k), k > 1, tenham sido substitudos por frmulas contendo
apenas T(1).

1 n/3K = 1 n = 3K

David Menotti

Algoritmos e Estrutura

Resolvendo a Equao
Considerando que T(n/3K) = T(1) temos:
K-1

K-1

i) + T(1) = n (1/3i) + 1
T(n) =
(n/3
i=0
i=0

Aplicando a frmula do somatrio de uma PG finita


(a0 rn)/(1-r), temos:
n (1 (1/3)K)/(1 -1/3) + 1
n (1 (1/3K))/(1 -1/3) + 1
n (1 (1/n))/(1 -1/3) + 1
(n 1)/(2/3) + 1
3n/2
David Menotti

O(n)
Algoritmos e Estrutura

Exerccio

Crie uma funo recursiva que calcula a


potncia de um nmero:

Como escrever a funo para o termo n em


funo do termo anterior?

Qual a condio de parada?

Qual a complexidade desta funo?

David Menotti

Algoritmos e Estrutura

Funo de Potncia
int pot(int base,Recursiva
int exp)
{
if (!exp)
return 1;
/* else */
return (base*pot(base, exp-1));
}
Anlise de complexidade:
T(0) = 1;
T(b,n) = 1 + T(b,n-1);

David Menotti

O(n)

Algoritmos e Estrutura

Exerccios

Implemente uma funo recursiva para


computar o valor de 2n

O que faz a funo abaixo?


void f(int a, int b) { // considere a > b
if (b = 0)
return a;
else
return f(b, a % b);
}

David Menotti

Algoritmos e Estrutura

Respostas

Pot(int n) {
if (n==0)
return 1;
else
return 2 * Pot(n-1);
}

Algoritmo de Euclides. Calcula o MDC


(mximo divisor comum) de dois nmeros
aeb

David Menotti

Algoritmos e Estrutura