Recursividade

265 visualizações

Publicada em

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.

Publicada em: Educação
0 comentários
0 gostaram
Estatísticas
Notas
  • Seja o primeiro a comentar

  • Seja a primeira pessoa a gostar disto

Sem downloads
Visualizações
Visualizações totais
265
No SlideShare
0
A partir de incorporações
0
Número de incorporações
4
Ações
Compartilhamentos
0
Downloads
6
Comentários
0
Gostaram
0
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

Recursividade

  1. 1. Tutoria AEDSI Pablo Silva
  2. 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.
  3. 3. Recursividade Uma função que chama à si mesmo é dita recursiva.
  4. 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. 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. 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. 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. 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", &nota); 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. 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", &nota); 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. 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", &nota); 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. 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", &nota); 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. 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", &nota); 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. 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", &nota); 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. 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", &nota); 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. 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", &nota); 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. 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", &nota); 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. 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. 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. 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. 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", &nota); 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. 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", &nota); 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. 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. 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. 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. 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", &nota); 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. 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", &nota); 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. 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", &nota); 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. 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. 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. 30. Vamos ver um exemplo int main(){ exemplo(‘c’); return 0; } 1 2 ? Passo 1: o programa se inicia.
  31. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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.
  61. 61. Recursividade Na primeira chamada tínhamos o seguinte passo recursivo: 1) 3 * fatorial(3-1)
  62. 62. Recursividade Na segunda chamada: 1) 3 * fatorial(3-1) 2) 2 * fatorial(2-1)
  63. 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.
  64. 64. Recursividade Logo: 1) return 3 * fatorial(3-1) 2) return 2 * fatorial(2-1) 3) return 1 1
  65. 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.
  66. 66. Recursividade Logo: 1) return 3 * fatorial(3-1) 2) return 2 3) return 1 2
  67. 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!
  68. 68. Recursividade Logo: 1) return 6 2) return 2 3) return 1 6 Assim se encerra a nossa função recursiva!
  69. 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. 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. 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. 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.

×