recursividade
TRANSCRIPT
Tutoria AEDSIPablo Silva
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.
Recursividade
Uma função que chama à si mesmo é dita recursiva.
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.
Calcular a mesadaSuponha 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.
Calcular a mesadaDigamos 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.
Calcular a mesadaNa 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.
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("\n\nO valor da mesada para seu filho e: %d", mesada);
return 0;}
1
23
45
6
7
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("\n\nO valor da mesada para seu filho e: %d", mesada);
return 0;}
1
23
45
6
7
8
?
?
?
Passo 1: variável mesada é criada sem valor algum por enquanto.
mesada
&43jjuiop
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("\n\nO valor da mesada para seu filho e: %d", mesada);
return 0;}
1
23
45
6
7
8
?
?
?
Passo 2: variável idade é criada sem valor algum por enquanto.
mesada
&43jjuiop
idade
&4399uiop
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("\n\nO valor da mesada para seu filho e: %d", mesada);
return 0;}
1
23
45
6
7
8
?
?
?
Passo 3: variável nota é criada sem valor algum por enquanto.
mesada
&43jjuiop
idade
&4399uiop
nota
&43666iop
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("\n\nO valor da mesada para seu filho e: %d", mesada);
return 0;}
1
23
45
6
7
8
?
?
?
Passo 4: mensagem exibida na tela:
Entre com a idade do seu filho:
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("\n\nO valor da mesada para seu filho e: %d", mesada);
return 0;}
1
23
45
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
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("\n\nO valor da mesada para seu filho e: %d", mesada);
return 0;}
1
23
45
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:
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("\n\nO valor da mesada para seu filho e: %d", mesada);
return 0;}
1
23
45
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
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("\n\nO valor da mesada para seu filho e: %d", mesada);
return 0;}
1
23
45
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!)
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
1213
1410
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!
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
1213
1410
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!
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
1213
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!
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("\n\nO valor da mesada para seu filho e: %d", mesada);
return 0;}
1
23
45
6
7
812
?
?
Passo 12: a caixinha de mesada recebe o valor de retorno da função.
13
200
mesada
&43jjuiop
200
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("\n\nO valor da mesada para seu filho e: %d", mesada);
return 0;}
1
23
45
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
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.
1415
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
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.
1415
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!
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.
1415
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!
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("\n\nO valor da mesada para seu filho e: %d", mesada);
return 0;}
1
23
45
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
&4399uiop
1
nota
&43666iop
14
200
200
mesada
&43jjuiop
200
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("\n\nO valor da mesada para seu filho e: %d", mesada);
return 0;}
1
23
45
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.
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("\n\nO valor da mesada para seu filho e: %d", mesada);
return 0;}
1
23
45
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 of0.2222s
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.
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 ?
Vamos ver um exemplo
int main(){exemplo(‘c’);return 0;
}
1
2
?
Passo 1: o programa se inicia.
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
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
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
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.
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.
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
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
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.
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
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
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.
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.
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!
Funções recursivasVamos ver um exemplo prático agora. Seja o fatorial matemático definido por n!:
1! = 12! = 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 base2) Passo recursivo
Funções recursivasVamos ver um exemplo prático agora. Seja o fatorial matemático definido por n!:
1! = 12! = 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?
Funções recursivasVamos ver um exemplo prático agora. Seja o fatorial matemático definido por n!:
1! = 12! = 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.
Funções recursivasVamos ver um exemplo prático agora. Seja o fatorial matemático definido por n!:
1! = 12! = 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.
Funções recursivasNossa 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!
Funções recursivasNossa 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.
Funções recursivasNossa 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.
Funções recursivasVamos 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
Funções recursivasVamos 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
Funções recursivasVamos 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
Funções recursivasVamos 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
Funções recursivasVamos 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
Funções recursivasVamos 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
Funções recursivasVamos 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
Funções recursivasVamos 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
Funções recursivasVamos 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
Recursividade
Entender para onde voltar quando atingimos o caso base é essencial para conseguirmos entender o que é recursividade. Vamos ver uma mapa desta execução.
RecursividadeNa primeira chamada tínhamos o seguinte passo recursivo:
1) 3 * fatorial(3-1)
RecursividadeNa segunda chamada:
1) 3 * fatorial(3-1)
2) 2 * fatorial(2-1)
RecursividadeNa 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.
RecursividadeLogo:
1) return 3 * fatorial(3-1)
2) return 2 * fatorial(2-1)
3) return 1
1
RecursividadeLogo:
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.
RecursividadeLogo:
1) return 3 * fatorial(3-1)
2) return 23) return 1
2
RecursividadeLogo:
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!
RecursividadeLogo:
1) return 62) return 2
3) return 1
6
Assim se encerra a nossa função recursiva!
Finalizando a execuçãoVamos 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
Funções recursivasVamos 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
82
Funções recursivasVamos 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!
Funções recursivasEscreva 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.