You are on page 1of 5

BC0505 Processamento da Informao

Assunto: Recursividade

1. Introduo: recursividade

Em um programa de computador muito comum chamarmos uma funo dentro de uma


outra funo. Entretanto, nada impede de uma funo chamar ela mesma! Como exemplo, vamos
pensar na funo fatorial. O fatorial de 3 e 6 respectivamente pode ser calculado conforme descrito
abaixo:
3! = 321 = 6
6! = 654321 = 720
De forma genrica, podemos calcular o fatorial como:
n!=n(n1)(n2)321
Deste modo, podemos facilmente implementar uma funo para calcular o fatorial:
class app {
static long fatorial(long n) {
long fat = 1;
for (long i = n; i > 1; i--) {
fat *= i;
}
return fat;
}

static public void main(String s[]) {


System.out.println(fatorial(3));
System.out.println(fatorial(6));
System.out.println(fatorial(10));
}
}

Uma outra forma de entender o fatorial :


3!=32!=32=6
6!=65!=6120=720
De modo genrico, temos:
n!=n(n1)!

1
Pela equao anterior, podemos deduzir que qualquer fatorial pode ser calculado
como o seu valor multiplicado pelo fatorial do seu valor subtrado por um. E quanto vale
o fatorial de n1? R: (n1)!=(n1)(n2)!
Podemos propor uma funo que tenta calcular a equao acima:
static long fatorial(long n) {
return n * (n-1)!
}

Entretanto, como podemos calcular o (n-1)!? A funo fatorial(n) que estamos


desenvolvendo no tem este objetivo? Ento, por que no utilizar esta prpria funo para calcular o
fatorial de (n-1)? Neste sentido, teremos:
static long fatorial(long n) {
return n * fatorial(n-1);
}

Entretanto, existe um erro grave nesta funo: se a funo chama ela mesma, quando esta
funo termina e retorna? R.: Da forma que est, no termina... :'(
O principal problema do exemplo anterior que a funo no sabe quando terminar! Deste
modo, toda funo recursiva precisa ter uma condio de trmino. Toda funo recursiva deve ter
uma lgica similar ao demonstrado a seguir:
static void funcRecursiva() {
// Parte Trivial
if (<conhecemos_a_resposta>)
return <resposta>;
// Parte Geral
else
return funcRecursiva();
}
No caso do fatorial, sabemos que o fatorial de 0 1. Esta a nossa parte TRIVIAL. Ento,
podemos alterar o cdigo fatorial recursivo proposto da seguinte forma:
static long fatorial(long n) {
// Parte Trivial
if (n <= 1)
return 1;

// Parte Geral
else
return n * fatorial(n-1);
}

Apesar de parecer que a recurso complica a soluo, conforme demonstrado no fatorial


(exemplo anterior), uma funo recursiva pode facilitar a implementao de muitos problemas,
pois permite dividir o problema em problemas menores para solucion-lo.
2
Para entender melhor a motivao do uso da recurso, vamos pegar um exemplo mais
complexo. Lembram da Torre de Hani? Caso no lembre, clique aqui.

Um algoritmo para solucionar a torre de Hani no trivial, mas podemos utilizar a recurso
com o objetivo de dividir para conquistar. A chave para resolver este problema quebrar o
desafio em desafios menores at que o desafio seja trivial. Neste caso, o trivial quando temos
apenas um nico disco para mover (neste caso, basta mover o disco direto).
Exemplificando, se queremos mover os discos da haste 1 para a haste 3, e existem n discos na
haste 1, podemos mover os n1 discos para a haste auxiliar 2, mover o ltimo disco da haste 1 para
a haste 3 e, ento, levar os n1 discos da haste auxiliar 2 para a haste 3. Veja a figura a seguir:

3
Ou seja, a parte TRIVIAL da nossa recurso mover um disco da haste 1 para a haste C. A
parte GERAL (recursiva) vai ser mover os n1 discos da haste 1 para a haste 2 e depois mover da
haste 2 para a haste 3. Um possvel algoritmo seria:

void hanoi(){
// Parte TRIVIAL
if (numero_de_discos == 1)
<mover_o_disco_da_origem_para_o_destino>

// Parte GERAL
else
hanoi(<mover_n-1_discos_da_origem_para_o_auxiliar)
<mover_o_disco_da_origem_para_o_destino>
hanoi(<mover_n-1_discos_do_auxiliar_para_o_destino)
}

Uma possvel implementao em Java apresentado a seguir.

class app {
static void Hanoi(int num_discos, String hasteOrigem,
String hasteDestino, String hasteAuxiliar) {
// Parte TRIVIAL
if (num_discos == 1) {
System.out.println("Mover o disco da haste " + hasteOrigem +
" para a haste " + hasteDestino + ".");

// Parte GERAL
} else {
Hanoi(num_discos-1, hasteOrigem, hasteAuxiliar, hasteDestino);
System.out.println("Mover o disco da haste " + hasteOrigem +
" para a haste " + hasteDestino + ".");
Hanoi(num_discos-1, hasteAuxiliar, hasteDestino, hasteOrigem);
}
}

static public void main(String s[]) {


Hanoi(4, "A", "B", "C");
}
}

Agora tente desenvolver uma outra soluo para o problema da torre de Hani sem utilizar a
recurso. Pense um pouco e voc perceber que muito difcil (porm no impossvel).

2. Atividades em sala

Exerccio 1. A sequncia de Fibonacci uma srie que segue a seguinte regra: xn=xn1+xn2,
sendo que x1=1 e x2=1. Os primeiros elementos da sequncia de Fibonacci so: {1, 1, 2, 3, 5, 8, 13,
21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, ... }. Um possvel cdigo
para imprimir a sequencia de Fibonacci apresentado abaixo:

4
class app {
static int Fibonacci(int n) {
int n1 = 1, n2 = 1;
for (int i = 3; i <= n; i++) {
int t = n1;
n1 = n2;
n2 = n1 + t;
}
return n2;
}
static public void main(String s[]) {
System.out.println(Fibonacci(3));
System.out.println(Fibonacci(6));
System.out.println(Fibonacci(9));
System.out.println(Fibonacci(12));
}
}
Faa um cdigo que calcule a sequncia de Fibonacci utilizando recurso.
Exerccio 2. Pode-se calcular o mximo divisor comum (MDC) entre dois nmeros inteiros
positivos utilizando o algoritmo de Euclides. Veja a implementao do algoritmo de Euclides
abaixo:
class app {
static int Euclides(int a, int b) {
while (b != 0) {
int t = a;
a = b;
b = t % b;
}
return a;
}
static public void main(String s[]) {
System.out.println(Euclides(10,8));
System.out.println(Euclides(21,13));
System.out.println(Euclides(63,108));
}
}
Modifique o algoritmo acima de modo a utilizar recurso.

3. Atividades para casa

Exerccio 01: Usando recursividade, calcule a soma de todos os valores de um vetor.


Exerccio 02: Usando recursividade, encontre o maior elemento de um vetor.
Exerccio 03: Faa uma funo recursiva que inverta os elementos de um vetor.
Exerccio 04: Crie uma funo recursiva que recebe os argumentos base e exp e calcule baseexp.
Considere que exp sempre inteiro. No permitido utilizar o operador de potncia ou lao de
repetio em nenhum momento.
Exerccio 05: Crie uma funo recursiva que verifica se um nmero n primo.
Exerccio 06: Escreva um algoritmo recursivo capaz de gerar todas as permutaes de uma String.

You might also like