Material de apoio das aulas de tutoria de Algoritmos e Estrutura de dados da Universidade Federal de Ouro Preto, Campus João Monlevade. O conteúdo abordado é sobre recursividade.
2. Recursividade
Muitos algoritmos têm a seguinte propriedade:
cada instância do problema contém uma instância
menor do mesmo problema. Dizemos que esses
problemas têm estrutura recursiva, porque é
possível resolver o problema chamando à si mesmo
com uma instância menor do problema.
4. Funções que chamam outras funções
Esse conceito tem que ficar bem claro: Uma função
pode chamar uma outra ou mais funções. Vamos ver
um exemplo.
5. Calcular a mesada
Suponha que queremos um programa para calcular a mesada de nossos filhos, baseado
em suas idades e notas. Seja então a seguinte função calcMesada. Não se preocupem
com a main, ela logo aparecerá. Não precisamos criar a main primeiro sempre, mas ela
terá que ser criada em algum momento!
O que esta função faz é receber um
parâmetro que será a idade do nosso
filho e retorna um valor maior da
mesada para filhos maiores de idade.
6. Calcular a mesada
Digamos agora que, a mesada de nossos filhos menores de idade, tem que ser recompensada (ou não!)
por suas notas. Então criamos a seguinte função que dá um bônus ou um desconto (bd) para nosso filho
menor de idade.
Essa função recebe três
parâmetros: a idade, a nota e o
valor da mesada já calculada
pela função anterior. Por isso é
muito importante chamar as
funções na ordem em que
queremos os resultados. Se não
calcularmos a mesada antes com
a outra função, como vamos
passa-la como parâmetro aqui!?Se a idade do nosso filho for menor que 18, vamos variar a mesada de
acordo com a nota dele, senão, vamos somente retornar o mesmo valor
da mesada que passamos para a função.
7. Calcular a mesada
Na main, vamos receber o
valor da idade e a nota
através da função scanf
(permite que o usuário
digite valores e armazena
nas variáveis passada como
parâmetro).
Após isso, chamamos a
função calcMesada para
calcular a mesada e
atribuímos este valor a
variável mesada.
Agora vamos chamar a
nossa segunda função e
passando como parâmetro
a própria mesada obtida
anteriormente.
8. Vamos executar este programa
int main(){
int mesada;
int idade;
int nota;
printf("Entre com a idade do seu filho:");
scanf("%d", &idade);
printf("Entre com a nota geral do seu filho:");
scanf("%d", ¬a);
mesada = calcMesada(idade);
mesada = bdMesada(idade,nota,mesada);
printf("nnO valor da mesada para seu filho e: %d", mesada);
return 0;
}
1
2
3
4
5
6
7
8
?
?
?
9. Vamos executar este programa
int main(){
int mesada;
int idade;
int nota;
printf("Entre com a idade do seu filho:");
scanf("%d", &idade);
printf("Entre com a nota geral do seu filho:");
scanf("%d", ¬a);
mesada = calcMesada(idade);
mesada = bdMesada(idade,nota,mesada);
printf("nnO valor da mesada para seu filho e: %d", mesada);
return 0;
}
1
2
3
4
5
6
7
8
?
?
?
Passo 1: variável mesada é criada
sem valor algum por enquanto.
mesada
&43jjuiop
10. Vamos executar este programa
int main(){
int mesada;
int idade;
int nota;
printf("Entre com a idade do seu filho:");
scanf("%d", &idade);
printf("Entre com a nota geral do seu filho:");
scanf("%d", ¬a);
mesada = calcMesada(idade);
mesada = bdMesada(idade,nota,mesada);
printf("nnO valor da mesada para seu filho e: %d", mesada);
return 0;
}
1
2
3
4
5
6
7
8
?
?
?
Passo 2: variável idade é criada sem
valor algum por enquanto.
mesada
&43jjuiop
idade
&4399uiop
11. Vamos executar este programa
int main(){
int mesada;
int idade;
int nota;
printf("Entre com a idade do seu filho:");
scanf("%d", &idade);
printf("Entre com a nota geral do seu filho:");
scanf("%d", ¬a);
mesada = calcMesada(idade);
mesada = bdMesada(idade,nota,mesada);
printf("nnO valor da mesada para seu filho e: %d", mesada);
return 0;
}
1
2
3
4
5
6
7
8
?
?
?
Passo 3: variável nota é criada sem
valor algum por enquanto.
mesada
&43jjuiop
idade
&4399uiop
nota
&43666iop
12. Vamos executar este programa
int main(){
int mesada;
int idade;
int nota;
printf("Entre com a idade do seu filho:");
scanf("%d", &idade);
printf("Entre com a nota geral do seu filho:");
scanf("%d", ¬a);
mesada = calcMesada(idade);
mesada = bdMesada(idade,nota,mesada);
printf("nnO valor da mesada para seu filho e: %d", mesada);
return 0;
}
1
2
3
4
5
6
7
8
?
?
?
Passo 4: mensagem exibida na tela:
Entre com a idade do seu filho:
13. Vamos executar este programa
int main(){
int mesada;
int idade;
int nota;
printf("Entre com a idade do seu filho:");
scanf("%d", &idade);
printf("Entre com a nota geral do seu filho:");
scanf("%d", ¬a);
mesada = calcMesada(idade);
mesada = bdMesada(idade,nota,mesada);
printf("nnO valor da mesada para seu filho e: %d", mesada);
return 0;
}
1
2
3
4
5
6
7
8
?
?
?
Passo 5: o usuário digita um valor para idade
e esse valor vai para a variável idade.
Entre com a idade do seu filho: 10
10
idade
&4399uiop
14. Vamos executar este programa
int main(){
int mesada;
int idade;
int nota;
printf("Entre com a idade do seu filho:");
scanf("%d", &idade);
printf("Entre com a nota geral do seu filho:");
scanf("%d", ¬a);
mesada = calcMesada(idade);
mesada = bdMesada(idade,nota,mesada);
printf("nnO valor da mesada para seu filho e: %d", mesada);
return 0;
}
1
2
3
4
5
6
7
8
?
?
?
Passo 6: mensagem é exibida na tela
Entre com a idade do seu filho: 10
Entre com a nota geral do seu filho:
15. Vamos executar este programa
int main(){
int mesada;
int idade;
int nota;
printf("Entre com a idade do seu filho:");
scanf("%d", &idade);
printf("Entre com a nota geral do seu filho:");
scanf("%d", ¬a);
mesada = calcMesada(idade);
mesada = bdMesada(idade,nota,mesada);
printf("nnO valor da mesada para seu filho e: %d", mesada);
return 0;
}
1
2
3
4
5
6
7
8
?
?
?
Passo 7: o usuário entra com o valor da nota
e esse valor vai direto para a variável nota.
Entre com a idade do seu filho: 10
Entre com a nota geral do seu filho: 1
1
nota
&43666iop
16. Vamos executar este programa
int main(){
int mesada;
int idade;
int nota;
printf("Entre com a idade do seu filho:");
scanf("%d", &idade);
printf("Entre com a nota geral do seu filho:");
scanf("%d", ¬a);
mesada = calcMesada(idade);
mesada = bdMesada(idade,nota,mesada);
printf("nnO valor da mesada para seu filho e: %d", mesada);
return 0;
}
1
2
3
4
5
6
7
8
?
?
?
Vamos para a função!
A seta está para cima porque
uma função que é chamada por
outra função sempre deve ser
declarada acima da função que à
está chamando. Do contrário, a
função não conseguirá chama-
la!
10
Estamos passando o valor
da idade e não uma
referência. Por isso nossa
caixinha só tem um valor
e nada de referências para
a variável idade.
(Recebemos este valor
anteriormente!)
17. Vamos executar este programa
int calcMesada(int idade){
if(idade < 18)
return idade*20;
else {
return idade*50;
}
}
Passo 9: Uma nova caixinha (varíavel)
chamada idade é criada e o valor que
“jogamos” (passamos como parâmetro na
chamada da função) para a função é
colocado lá dentro.
10
9
10
11
12
13
14
10
idade
&9999uiop
Muito importante entender aqui
que essa caixinha tem o mesmo
nome que a caixinha da idade que
está na main. Mas como pode ser
visto os endereços são diferentes.
ELAS NÃO SÃO A MESMA VARIÁVEL,
SOMENTE TEM O MESMO NOME.
Já sabemos que não podemos ter
duas variáveis com o mesmo nome,
mas esta regra é válida para
mesmas funções. Funções
diferentes podem ter variáveis com
mesmo nome, que é o nosso caso!
Lembre-se, uma função não consegue ver
nada que está dentro de outra função. O
escopo de uma função é digamos
“secreto” para todas as outras!
18. Vamos executar este programa
int calcMesada(int idade){
if(idade < 18)
return idade*20;
else {
return idade*50;
}
}
Passo 10: Verificamos se a idade é menor
que 18. Para este nosso caso ela é, então o
passo 11 será executado!
9
10
11
12
13
14
10
idade
&9999uiop
Lembre-se, uma função não consegue ver
nada que está dentro de outra função. O
escopo de uma função é digamos
“secreto” para todas as outras!
19. Vamos executar este programa
int calcMesada(int idade){
if(idade < 18)
return idade*20;
else {
return idade*50;
}
}
Passo 11: Encontramos a palavra return.
Portanto neste momento vamos retornar o
valor da multiplicação de idade por 20 para o
local onde esta função foi chamada. Neste
caso é a na main.9
10
11
12
13
10
idade
&9999uiop
Importante: os passos 12, 13 nunca serão
executados, pois uma vez que em uma
função, é encontrado a palavra de retorno, ela
imediatamente interrompe sua execução e
retorna o valor passado para o return.
200
Só podemos retornar valores que já temos. Por
isso, o retorno para a main só vai acontecer
quando o computador processar a operação
idade*20 e substituir o valor desta multiplicação
na expressão. Se o computador demorasse 10
anos para computar esta multiplicação, então
demoraríamos 10 anos para voltar para a main!
20. Vamos executar este programa
int main(){
int mesada;
int idade;
int nota;
printf("Entre com a idade do seu filho:");
scanf("%d", &idade);
printf("Entre com a nota geral do seu filho:");
scanf("%d", ¬a);
mesada = calcMesada(idade);
mesada = bdMesada(idade,nota,mesada);
printf("nnO valor da mesada para seu filho e: %d", mesada);
return 0;
}
1
2
3
4
5
6
7
812
?
?
Passo 12: a caixinha de
mesada recebe o valor de
retorno da função.
13
200
mesada
&43jjuiop
200
21. Vamos executar este programa
int main(){
int mesada;
int idade;
int nota;
printf("Entre com a idade do seu filho:");
scanf("%d", &idade);
printf("Entre com a nota geral do seu filho:");
scanf("%d", ¬a);
mesada = calcMesada(idade);
mesada = bdMesada(idade,nota,mesada);
printf("nnO valor da mesada para seu filho e: %d", mesada);
return 0;
}
1
2
3
4
5
6
7
812
?
?
Passo 13: vamos novamente para outra
função. Chamamos bdMesada enviando os
valores dos nossos três parâmetros!
(Passagem por valor!)
13
200
mesada
&43jjuiop
10
idade
&4399uiop
1
nota
&43666iop
10
1
200
22. Vamos executar este programa
int bdMesada(int idade, int notas, int mesada){
if(idade < 18)
return mesada*notas;
return mesada;
}
Passo 14: São criadas novas caixinhas para os
nossos parâmetros que vão receber os
valores enviados na chamada da função, na
mesma ordem enviada.
14
15
16
17
Lembre-se, uma função não consegue ver
nada que está dentro de outra função. O
escopo de uma função é digamos
“secreto” para todas as outras!
200
mesada
&99yjuiop
10
idade
&4oouiop
1
nota
&4wertiop
MESMOS NOMES, MAS
ENDEREÇOS DIFERENTES!
10 1 200
23. Vamos executar este programa
int bdMesada(int idade, int notas, int mesada){
if(idade < 18)
return mesada*notas;
return mesada;
}
Passo 15: Vamos ver se a idade é menor que
18. Para o nosso caso é, então vamos
executar o passo 16.
14
15
16
17
Lembre-se, uma função não consegue ver
nada que está dentro de outra função. O
escopo de uma função é digamos
“secreto” para todas as outras!
200
mesada
&99yjuiop
10
idade
&4oouiop
1
nota
&4wertiop
MESMOS NOMES, MAS
ENDEREÇOS DIFERENTES!
24. Vamos executar este programa
int bdMesada(int idade, int notas, int mesada){
if(idade < 18)
return mesada*notas;
return mesada;
}
Passo 16: Encontramos a palavra return e
então vamos retornar para o local que esta
função foi chamada, retornando o valor de
mesada*notas que para nosso caso é 200*1
= 200. O passo 17 então não será executado,
pois interrompemos a execução no
momento do retorno.
14
15
16
17
Lembre-se, uma função não consegue ver
nada que está dentro de outra função. O
escopo de uma função é digamos
“secreto” para todas as outras!
200
mesada
&99yjuiop
10
idade
&4oouiop
1
nota
&4wertiop
200
Novamente, retornamos
valores e nunca expressões!
Para que a função retorne para
onde foi chamada, o
computador primeiro tem que
fazer a multiplicação e devolver
um valor para o retorno!
25. Vamos executar este programa
int main(){
int mesada;
int idade;
int nota;
printf("Entre com a idade do seu filho:");
scanf("%d", &idade);
printf("Entre com a nota geral do seu filho:");
scanf("%d", ¬a);
mesada = calcMesada(idade);
mesada = bdMesada(idade,nota,mesada);
printf("nnO valor da mesada para seu filho e: %d", mesada);
return 0;
}
1
2
3
4
5
6
7
812
15
16
Passo 14: a caixinha da mesada, vai receber
o valor de retorno da função. Como já
tínhamos um valor lá, ele será substituído
pelo novo. Coincidentemente, este valor é o
mesmo, porque nossa multiplicação na
função foi por 1. De qualquer maneira o
valor será substituído, mesmo que seja pelo
mesmo valor!
13
10
idade
&4399ui
1
nota
&43666iop
14
200
200
mesada
&43jjuiop
200
26. Vamos executar este programa
int main(){
int mesada;
int idade;
int nota;
printf("Entre com a idade do seu filho:");
scanf("%d", &idade);
printf("Entre com a nota geral do seu filho:");
scanf("%d", ¬a);
mesada = calcMesada(idade);
mesada = bdMesada(idade,nota,mesada);
printf("nnO valor da mesada para seu filho e: %d", mesada);
return 0;
}
1
2
3
4
5
6
7
812
15
16
Passo 15: É exibida uma mensagem na tela com o valor
da variável mesada, que é a saída final do nosso
programa e o objetivo que queríamos atingir.
1314
200
Entre com a idade do seu filho: 10
Entre com a nota geral do seu filho: 1
O valor da mesada para seu filho e: 200.
27. Vamos executar este programa
int main(){
int mesada;
int idade;
int nota;
printf("Entre com a idade do seu filho:");
scanf("%d", &idade);
printf("Entre com a nota geral do seu filho:");
scanf("%d", ¬a);
mesada = calcMesada(idade);
mesada = bdMesada(idade,nota,mesada);
printf("nnO valor da mesada para seu filho e: %d", mesada);
return 0;
}
1
2
3
4
5
6
7
812
15
16
Passo 16: Programa termina. É exibida na tela uma
mensagem padrão da linguagem.
1314
200 Entre com a idade do seu filho: 10
Entre com a nota geral do seu filho: 1
O valor da mesada para seu filho e: 200.
Program returned with execution of
0.2222s
28. Recursividade
Como já vimos que uma função pode chamar uma
ou mais funções, então não há porque duvidar que
uma função pode chamar à ela mesma! Vamos ver
como funciona então uma função recursiva.
29. Vamos ver um exemplo
int main(){
exemplo(‘c’);
return 0;
}
void exemplo(char a){
printf(“%c”, a);
exemplo(a);
}
Digamos que temos a função exemplo e chamamos ela na main passando o caracter ‘c’. Vamos ver como
será a execução.
1
2
3
4
5 ?
30. Vamos ver um exemplo
int main(){
exemplo(‘c’);
return 0;
}
1
2
?
Passo 1: o programa se inicia.
31. Vamos ver um exemplo
int main(){
exemplo(‘c’);
return 0;
}
1
2
?
Passo 2: vamos para a função e estamos
passando o caracter ‘c’ utilizando passagem
por valor. Dessa vez nem mesmo temos
variáveis na main. Só estamos querendo
chamar a função para ver o qual é seu
comportamento recursivo.
c
32. Vamos ver um exemplo
void exemplo(char a){
printf(“%c”, a);
exemplo(a);
}
3
4
5
Passo 3: Uma variável (caixinha) do tipo
char é criada e o valor passado na
chamada da função é atribuído à ela.
c
c
a
&3399uiop
33. Vamos ver um exemplo
void exemplo(char a){
printf(“%c”, a);
exemplo(a);
}
3
4
5
Passo 4: Imprimimos o caracter que está
na variável a na tela.
c
a
&3399uiop
c
34. Vamos ver um exemplo
void exemplo(char a){
printf(“%c”, a);
exemplo(a);
}
3
4
5
Passo 5: O passo cinco é chamado passo
recursivo, que é quando chamamos a
mesma função dentro dela. Veja, estamos
passando a variável a por valor. Logo,
vamos jogar novamente a letra c para a
função.
c
a
&3399uiop
c
Muito importante lembrar que,
quando uma função termina o seu
escopo, tudo que está dentro dela
é destruído. Portanto a caixinha a
será destruída e recriada,
possivelmente em um novo
endereço.
35. Vamos ver um exemplo
void exemplo(char a){
printf(“%c”, a);
exemplo(a);
}
3
4
5
Passo 3: Uma nova caixinha (variável) de
nome a será criada e armazenará o valor
que passamos na chamada da função.
c
a
&3633uiop
c
Provavelmente esta nova
caixinha terá um novo
endereço. A memória é
bastante aleatória.
36. Vamos ver um exemplo
void exemplo(char a){
printf(“%c”, a);
exemplo(a);
}
3
4
5
Passo 4: Imprimimos novamente a letra c
na tela.
cc
37. Vamos ver um exemplo
void exemplo(char a){
printf(“%c”, a);
exemplo(a);
}
3
4
5
Passo 5: Chamamos novamente a nossa
função. Outro passo recursivo. E tudo
recomeça outra vez.
c
a
&3633uiop
c
38. Vamos ver um exemplo
void exemplo(char a){
printf(“%c”, a);
exemplo(a);
}
3
4
5
Passo 3: Uma nova caixinha (variável) de
nome a será criada e armazenará o valor
que passamos na chamada da função.
c
a
&456guiop
c
Provavelmente esta nova
caixinha terá um novo
endereço. A memória é
bastante aleatória.
39. Vamos ver um exemplo
void exemplo(char a){
printf(“%c”, a);
exemplo(a);
}
3
4
5
Passo 4: Imprimimos novamente a letra c
na tela.
ccc
40. Vamos ver um exemplo
void exemplo(char a){
printf(“%c”, a);
exemplo(a);
}
3
4
5
Passo 5: Chamamos novamente a nossa
função. Outro passo recursivo. E tudo
recomeça outra vez.
c
a
&3633uiop
c
41. Recursividade
CHEGAAAAAA! UFF! Como fazer a recursão parar?
Pois é, esta é outra característica de uma função
recursiva. Ela precisa sempre ter um Caso Base, que
vai determinar quando ela vai parar de se chamar.
42. Caso base
void exemplo(char a){
printf(“%c”, a);
exemplo(a);
}
Para esta função, nem conseguiríamos criar um
caso base sem que tivéssemos mais um
parâmetro, que frequentemente é o contador dos
passos recursivos. Esse contador sempre é
diminuído por um fator qualquer (depende do
nosso problema) até que ele encontre um caso
base.
Esta característica torna a recursão, uma
resolução de problemas por instâncias menores
do mesmo problema.
A cada passo recursivo, o nosso problema
diminui, até que cheguemos no caso base, que
será a menor instância do nosso problema.
43. Caso base
void exemplo(char a){
printf(“%c”, a);
exemplo(a);
}
É muito importante
modelar a função recursiva
de maneira correta, pois
senão, como vimos, nosso
programa pode entrar em
loop e nunca parar!
44. Funções recursivas
Vamos ver um exemplo prático agora. Seja o fatorial matemático
definido por n!:
1! = 1
2! = 2*1 = 2*1!
3! = 3*2*1 = 3*2!
4! = 4*3*2*1 = 4*3!
5! = 5*4*3*2*1 = 5*4!
.....................................
n! = n*(n-1)*(n-2)*...*(1) = n*(n-1)!
Para criar uma função recursiva que
resolva este problema, precisamos
encontrar dois elementos essenciais
para a recursão:
1) Caso base
2) Passo recursivo
45. Funções recursivas
Vamos ver um exemplo prático agora. Seja o fatorial matemático
definido por n!:
1! = 1
2! = 2*1 = 2*1!
3! = 3*2*1 = 3*2!
4! = 4*3*2*1 = 4*3!
5! = 5*4*3*2*1 = 5*4!
.....................................
n! = n*(n-1)*(n-2)*...*(1) = n*(n-1)!
O caso base é muito simples, e
logicamente que é 1. Se olharmos para
todas as linhas, elas sempre terminam
no 1 e por isso ele é o nosso caso base.
Pense no caso base, como o elemento
que sempre vai ser atingindo em algum
momento e ele deve ser, pois do
contrário como vamos parar a recursão?
46. Funções recursivas
Vamos ver um exemplo prático agora. Seja o fatorial matemático
definido por n!:
1! = 1
2! = 2*1 = 2*1!
3! = 3*2*1 = 3*2!
4! = 4*3*2*1 = 4*3!
5! = 5*4*3*2*1 = 5*4!
.....................................
n! = n*(n-1)*(n-2)*...*(1) = n*(n-1)!
O passo recursivo é aquele em que
diminuímos a instância do nosso
problema por algum fator. Para o nosso
caso ele é dado pela nossa fórmula geral:
n*(n-1)!
Vamos entender o por que.
47. Funções recursivas
Vamos ver um exemplo prático agora. Seja o fatorial matemático
definido por n!:
1! = 1
2! = 2*1 = 2*1!
3! = 3*2*1 = 3*2!
4! = 4*3*2*1 = 4*3!
5! = 5*4*3*2*1 = 5*4!
.....................................
n! = n*(n-1)*(n-2)*...*(1) = n*(n-1)!
n*(n-1)! nos diz o seguinte:
Multiplique a instância do meu problema de
valor n por uma nova instância de valor n-1.
Para encontrarmos o valor da instância n-1
vamos ter que realizar novamente o fatorial.
Percebe que utilizamos o fatorial novamente
para calcular (n-1)!. Com certeza este é o nosso
passo recursivo, pois a cada chamada, vamos
diminuir a instância do nosso problema por um
fator de 1.
48. Funções recursivas
Nossa função então ficaria da seguinte maneira:
int fatorial(int n){
}
A função tem que
retornar um inteiro, pois é
o valor do fatorial que
queremos encontrar!
49. Funções recursivas
Nossa função então ficaria da seguinte maneira:
int fatorial(int n){
if( n == 1 )
return 1;
}
Sempre numa função recursiva,
a primeira coisa a fazer é
colocar o caso base. Sabemos
que o fatorial de 1 é 1 e então
este será o nosso valor de
retorno.
50. Funções recursivas
Nossa função então ficaria da seguinte maneira:
int fatorial(int n){
if( n == 1 )
return 1;
return n * fatorial(n-1);
}
Agora então definimos nosso
passo recursivo, dado pela
fórmula geral. O passo recursivo
é exatamente a nossa fórmula
geral, porém escrito na
linguagem de programação e
não numa fórmula matemática.
E nossa função recursiva está
pronta! Vamos testá-la.
51. Funções recursivas
Vamos assumir que chamamos esta função na main e passamos o valor 3 na chamada.
int fatorial(int n){
if( n == 1 )
return 1;
return n * fatorial(n-1);
}
3
1
2
3
4
Passo 1: uma caixinha para n é
criada e o valor 3 colocado lá
dentro.
3
n
&3633uiop
52. Funções recursivas
Vamos assumir que chamamos esta função na main e passamos o valor 3 na chamada.
int fatorial(int n){
if( n == 1 )
return 1;
return n * fatorial(n-1);
}
1
2
3
4
Passo 2: verificamos se atingimos
nosso caso base. Como n não é
igual a 1, ainda não o atingimos.
Pulamos então para o passo 4.
3
n
&3633uiop
53. Funções recursivas
Vamos assumir que chamamos esta função na main e passamos o valor 3 na chamada.
int fatorial(int n){
if( n == 1 )
return 1;
return n * fatorial(n-1);
}
1
2
3
4
Passo 4: Passo recursivo. Vamos
chamar nossa função novamente
passando um novo valor de n.
3
n
&3633uiop
2
54. Funções recursivas
Vamos assumir que chamamos esta função na main e passamos o valor 3 na chamada.
int fatorial(int n){
if( n == 1 )
return 1;
return n * fatorial(n-1);
}
5
6
7
8
Passo 5: Uma nova caixinha para n
é criada e o valor de chamada é
atribuído à ela.
2
n
&2223uiop
2
55. Funções recursivas
Vamos assumir que chamamos esta função na main e passamos o valor 3 na chamada.
int fatorial(int n){
if( n == 1 )
return 1;
return n * fatorial(n-1);
}
5
6
7
8
Passo 6: Verificamos novamente o
nosso caso base. Ainda não o
atingimos, e então o passo 7 será
pulado.
2
n
&2223uiop
56. Funções recursivas
Vamos assumir que chamamos esta função na main e passamos o valor 3 na chamada.
int fatorial(int n){
if( n == 1 )
return 1;
return n * fatorial(n-1);
}
5
6
7
8
Passo 8: Uma nova chamada
recursiva é realizada com uma
instância ainda menor do
problema.
2
n
&2223uiop
1
57. Funções recursivas
Vamos assumir que chamamos esta função na main e passamos o valor 3 na chamada.
int fatorial(int n){
if( n == 1 )
return 1;
return n * fatorial(n-1);
}
9
10
11
12
Passo 9: Novamente uma nova
caixinha para n é criada, e o valor
passado na chamada é atribuído
para ela.
1
n
&9923uiop
1
58. Funções recursivas
Vamos assumir que chamamos esta função na main e passamos o valor 3 na chamada.
int fatorial(int n){
if( n == 1 )
return 1;
return n * fatorial(n-1);
}
9
10
11
12
Passo 10: Verificamos o nosso caso
base e percebemos que acabamos
de atingí-lo! Então o passo 12 não
será executado.
1
n
&9923uiop
1
59. Funções recursivas
Vamos assumir que chamamos esta função na main e passamos o valor 3 na chamada.
int fatorial(int n){
if( n == 1 )
return 1;
return n * fatorial(n-1);
}
9
10
11
12
Passo 11: Mas e agora,
encontramos a palavra
return, para onde temos
que retornar? Para a
main?
1
n
&9923uiop
60. Recursividade
Entender para onde voltar quando atingimos o caso
base é essencial para conseguirmos entender o que
é recursividade. Vamos ver uma mapa desta
execução.
63. Recursividade
Na terceira chamada:
1) return 3 * fatorial(3-1)
2) return 2 * fatorial(2-1)
3) return 1
A terceira chamada foi onde encontramos o nosso
caso base. Dessa maneira, o valor de retorno da
chamada em que o caso base é encontrado deve ser
retornado para exatamente a última chamada
efetuada antes do caso base.
Perceba que todas as chamadas são também
retornos e mais uma vez, um retorno só pode conter
valores já definidos. O que acontece nas chamadas 2
e 3, é que elas estão esperando valores de retorno
para poderem realizar a multiplicação. Já na chamada
3 não, 1 já é um valor definido e não tem que realizar
nenhuma operação.
65. Recursividade
Logo:
1) return 3 * fatorial(3-1)
2) return 2 *
3) return 1
1
Agora a chamada 2 pode realizar a
multiplicação e retornar seu valor
para a chamada 1.
67. Recursividade
Logo:
1) return 3 *
2) return 2
3) return 1
2
Por fim, a chamada 3 pode realizar
também a multiplicação e retornar
para onde foi chamada. Como vimos
no começo, assumimos que chamamos
a função fatorial na main e então é pra
lá que o retorno da primeira chamada
irá voltar, devolvendo enfim o valor do
fatorial de 3 que é 6!
69. Finalizando a execução
Vamos assumir que chamamos esta função na main e passamos o valor 3 na chamada.
int fatorial(int n){
if( n == 1 )
return 1;
return n * fatorial(n-1);
}
9
10
11
12
1
70. Funções recursivas
Vamos assumir que chamamos esta função na main e passamos o valor 3 na chamada.
int fatorial(int n){
if( n == 1 )
return 1;
return n * fatorial(n-1);
}
5
6
7
8
2
71. Funções recursivas
Vamos assumir que chamamos esta função na main e passamos o valor 3 na chamada.
int fatorial(int n){
if( n == 1 )
return 1;
return n * fatorial(n-1);
}
1
2
3
4
2
6
Voltando pra main com 6!
72. Funções recursivas
Escreva uma função recursiva que retorne o valor de um número elevado por n.
Exemplo:
exp(4,2) -> significa que queremos elevar 4 ao quadrado.
Quem fizer este exercício e me explicar na sala, poderá errar um exercício no
mini-teste.