Você está na página 1de 15

Algoritmos Recursivos

Conceito de Recursividade

• Um programa recursivo é um programa que


chama a si mesmo, direta ou indiretamente
• Conceito poderoso
– Define conjuntos infinitos com comandos finitos
• Vantagens
– Redução do tamanho do código fonte
– Permite descrever algoritmos de forma mais clara e
concisa
• Desvantagens
– Redução do desempenho de execução devido ao tempo
para gerenciamento de chamadas
– Dificuldades na depuração de programas recursivos,
especialmente se a recursão for muito profunda
Implementação da Recursividade

• Usa-se uma pilha para armazenar os dados


usados em cada chamada de um procedimento /
função que não terminou
• Todos os dados não globais são armazenados na
pilha, informando o resultado corrente
• Quando uma ativação anterior prossegue, os
dados da pilha são recuperados
Exemplo – Função Fatorial

• Definição de uma Função Fatorial


a) Não Recursiva:
– N! = 1, para N=0;
– N! = 1 x 2 x 3 x ... x N, para N>=1;
b) Recursiva:
– N! = 1, para N=0;
– N! = N x (N – 1), para N>=1;
Implementação de Fatorial
Recursivo X Não Recursivo

Implementação não Recursiva Implementação Recursiva


Function Fatorial (n: integer): real; Function Fatorial (n: integer): real;
var i : integer; result: real; begin
begin If n = 0 then
result :=1; Fatorial := 1
for i:= 2 to n do Else
result := result * i; Fatorial := n * Fatorial (n-1);
Fatorial:= result; end;
end;
Resultado da Implementação

Fatorial := 1

1
Fatorial := 1 * (Fatorial(0)) Fatorial = 1

1
Fatorial := 2 * (Fatorial(1)) Fatorial = 2

2
Fatorial := 3 * (Fatorial(2)) Fatorial = 6

Fatorial := 4 * (Fatorial(3))
6 Fatorial = 24
Problema com terminação de
Procedimentos Recursivos
• Procedimentos recursivos introduzem a possibilidade de
iterações que podem não terminar: existe a necessidade de
considerar o problema de terminação.

• É fundamental que a chamada recursiva a um


procedimento P esteja sujeita a uma condição A, a qual se
torna satisfeita em algum momento da computação.
– Ex.: Se não existisse a condição n=0, quando o procedimento
terminaria?

• Condição de terminação
– Permite que o procedimento deixe de ser executado
– O procedimento deve ter pelo menos um caso básico para
cada caso recursivo, o que significa a finalização do
procedimento
Outro Exemplo - Busca em uma Lista
Linear Ordenada
• Pode-se realizar a busca em um elemento de
duas formas:
– Busca Seqüencial
– Busca Binária
• Busca Seqüencial: elementos são pesquisados
de acordo com o índice
– Pior caso: o elemento está no último índice do meu
vetor.
– Imagine realizar uma busca seqüencial em uma Lista
Telefônica!
Busca Seqüencial

Procedure Busca_Sequencial(L: TipoLista; x: TipoItem);


Var
i: integer;
Begin
i:=1;
while ( L.Item[i]) <> x and i<=L.Ultimo – 1 do
i:= i+1;
if L.Item[i] = x then
Writeln (‘Elemento Encontrado’);
else
Writeln (‘Elemento Não Encontrado’);
End;
Busca Seqüencial

Procurar por R

A C E H L M P R T Z

-8 Comparações!
-Se eu estivesse procurando o item Z, o número de comparações
seria a quantidade de elementos no vetor
-O ideal seria dividir o vetor pela metade para então procurar (Busca
Binária)
Busca Binária

• Divide seu vetor em duas metades


• Três condições
1. Se o item for igual ao item que está na metade do vetor,
o item foi encontrado
2. Se for menor, procure na primeira metade
3. Se for maior procure na segunda metade

– Veja uma visualização no próximo slide


Busca Binária

Procurar por R
1 2 3 4 5 6 7 8 9 10

A C E H L M P R T Z

I X I X F

-2 Comparações!
-Casos piores: quando os itens estiverem no início do vetor. Nesse
caso, seria melhor utilizar busca seqüencial. Mas como saber quando
o ítem está no início do vetor?
Busca Binária
Procedure Busca_Binária(L: TipoLista; x: TipoItem; Inicio, Fim: integer);
Var
meio: integer;
Begin
meio := (inicio + fim) div 2;
If fim < inicio then
Writeln (‘Elemento Não Enontrado’)
Else If (L.Item[meio]) = x then
Writeln (‘Elemento está na posição ’ + meio)
Else
If L.Item[meio] < x then begin
inicio := meio +1;
Busca_Binaria (L, x, inicio, fim);
end else
fim := meio - 1;
Busca_Binaria (L, x, inicio, fim);
end;
End;
Dicas

• Não se aprende recursividade sem praticar


• Para montar um algoritmo recursivo
– Defina pelo menos um caso básico (condição de
terminação);
– Quebre o problema em problemas menores,
definindo o(s) caso(s) com recursão(ões)
– Fazer o teste de finitude, isto é, certificar-se de
que as sucessivas chamadas recursivas levam
obrigatoriamente, e numa quantidade finita de
vezes, ao(s) caso(s) básico(s)
Finalizando

• Recursividade é um tópico fundamental


• Algoritmos recursivos aparecem bastante na
prática
• Dividir e conquistar é uma técnica naturalmente
recursiva para solução de problemas

• Mais recursividade no nosso futuro,


principalmente na implementação de árvores...

Você também pode gostar