Você está na página 1de 16

Instituto Federal de Goiás

Câmpus Goiânia
Bacharelado em Sistemas de Informação
Disciplina: Estruturas de Dados II

Recursividade

Prof. Ms. Renan Rodrigues de Oliveira


Goiânia - GO
Introdução
É uma técnica de programação na qual um método
chama a si mesmo.

A ideia é dividir um problema original um subproblemas menores de


mesma natureza (divisão) e depois combinar as soluções obtidas para
gerar a solução do problema original de tamanho maior (conquista).
 Os subproblemas são resolvidos Exemplo: Função Fatorial
recursivamente do mesmo modo em
função de instâncias menores, até
se tornarem problemas triviais que
são resolvidos de forma direta,
interrompendo a recursão.
Exemplo: Multiplicação de Números Naturais

Definição não recursiva (tradicional):


 A = 1, para n = 0.
 n! = 1 × 2 × 3 × ... × n, para n>0.

Definição recursiva:
 n! = 1, para n = 0;
 n! = n × (n-1)!, para n > 0.
Implementação Iterativa
Definição não recursiva (tradicional):
 n! = 1, para n = 0.
 n! = 1 × 2 × 3 × .... × n, para n > 0.

Implementação Iterativa
Implementação Recursiva
Definição recursiva:
 n! = 1, para n = 0;
 n! = n × (n-1)!, para n > 0.

Implementação Recursiva
Chamada de Método
Mas como o programa diferencia a variável n da primeira chamada da
variável n da segunda chamada do método fatorial?

Quando um método é chamado:


 É necessário inicializar os
parâmetros com os valores
passados como argumento;
 O sistema precisa saber onde reiniciar a execução do programa.
 Informações de cada método (variáveis e endereço de retorno) devem
ser guardadas até o método acabar a sua execução.
Registro de Ativação
Registro de Ativação é uma área de memória que guarda o
estado de uma função.

Estado de uma função:


 variáveis locais;
 valores dos parâmetros;
 endereço de retorno (instrução após a chamada do método corrente);
 valor de retorno.
Registro de Ativação
 Registro de ativação são criados em uma pilha em tempo de execução;
 Existe um registro de ativação (um nó na pilha) para cada método;
 Quando um método é chamado é criado um registro de ativação para este e
este é empilhado na pilha;
 Quando o método finaliza sua execução o registro de ativação desse método
é desalocado.

Registro de Ativação
Chamada de Método

Programa Principal
Registro de Ativação
Registro de
Ativação
Fat(0)

Registro de
Ativação
Fat(1)

Registro de
Ativação
Fat(2)

Registro de
 A cada término de FAT, o controle retorna para a Ativação
Fat(3)
expressão onde foi feita a chamada na execução
anterior, e o último conjunto de variáveis que foi
alocado é liberado nesse momento. Esse mecanismo Registro de
Ativação
utiliza uma pilha. Fat(4)

 A cada nova chamada do método FAT, um novo


conjunto de variáveis (n, FAT) é alocado.
Exemplo: Multiplicação de Números Naturais

Outro exemplo de uma definição recursiva é a definição da


multiplicação de números naturais.
 O produto a * b, em que a e b são inteiros positivos, pode ser definido
como a somado a si mesmo b vezes.

Definição recursiva:
 a × b = a, se b = 1;
 a × b = a + a × (b - 1), se b > 1.
Exemplo: Sequência de Fibonacci
A sequência de Fibonacci é a sequência de inteiros:
 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
 Cada elemento nessa sequência é a soma dos dois elementos
anteriores. Por exemplo: 1+1=2; 1+2=3; 2+3=5 ...

Se partirmos que fib(0)=0 e fib(1)=1 e assim por diante, podemos


definir um número da sequência de Fibonnaci da seguinte maneira:
 fib(n) = n, se n ≤ 2;
 fib(n) = fib(n-2) + fib(n-1), se n > 2.
Exemplo: Sequência de Fibonacci
Implementação Iterativa  A solução recursiva é muito mais simples de
programar do que a versão iterativa.
 Contudo, esta versão é ineficiente, pois cada vez
que a função fib_r é chamada, são feitas duas
chamadas recursivas.
 Isto dá origem a uma explosão combinatória e o
computador acaba por ter de calcular o mesmo
termo várias vezes.

Implementação Recursiva
Exemplo: Sequência de Fibonacci
Usando a implementação recursiva, para calcular fib(5) foi preciso
calcular fib(4) 1 vez, fib(3) 2 vezes, fib(2) 3 vezes e fib(1) 2 vezes.
 Este tipo de processamento é inadequado, já que o computador é
obrigado a fazer trabalho desnecessário.
 Na implementação iterativa, apenas foi necessário calcular fib(5),
fib(4), fib(3), fib(2) e fib(1) apenas 1 vez.

Chamadas recursivas
para calcular fib(7).
Vantagens
A principal vantagem das funções recursivas é a possibilidade de utilizá-
las para criar versões mais claras e simples de vários algoritmos

Embora uma solução não recursiva envolvendo outras estruturas


(pilhas, filas etc.) seja mais difícil de desenvolver e mais propensa a
erros.
 Dessa forma, ocorre um conflito entre a eficiência da máquina e a do
programador.

O custo da programação está aumentando e o custo da computação


está diminuindo.
 Isto leva a um cenário que não vale a pena para um programador
demandar muito tempo para elaborar programas iterativos quando
soluções recursivas podem ser escritas mais rapidamente.
Cuidados com Recursividade
Ao escrever funções recursivas, deve-se ter um comando if em
algum lugar para forçar a função a retornar sem que a chamada
recursiva seja executada.

Se isto não existir, a função nunca retornará quando chamada.

 Omitir o comando if é um erro comum quando se escrevem funções


recursivas.
 Isto garante que o programa recursivo não gere uma sequência
infinita de chamadas a si mesmo.
Cuidados com Recursividade
As versões recursivas da maioria das rotinas podem ser executadas um
pouco mais lentamente que suas equivalentes iterativas devido às
repetidas chamadas à função.

De fato, muitas chamadas recursivas a uma função podem provocar um


estouro da pilha.
 Como o armazenamento para os parâmetros da função e variáveis
locais está na pilha e cada nova chamada cria uma nova cópia dessas
variáveis, a pilha pode provavelmente escrever sobre outra memória
de dados ou de programa.
 Contudo, não é necessário se preocupar com isso, a menos que uma
função recursiva seja executada de forma desenfreada.

Você também pode gostar