recursividade

72
Tutoria AEDSI Pablo Silva

Upload: pablo-silva

Post on 08-Aug-2015

33 views

Category:

Education


1 download

TRANSCRIPT

Page 1: Recursividade

Tutoria AEDSIPablo Silva

Page 2: Recursividade

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.

Page 3: Recursividade

Recursividade

Uma função que chama à si mesmo é dita recursiva.

Page 4: Recursividade

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.

Page 5: Recursividade

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.

Page 6: Recursividade

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.

Page 7: Recursividade

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.

Page 8: Recursividade

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("\n\nO valor da mesada para seu filho e: %d", mesada);

return 0;}

1

23

45

6

7

8

?

?

?

Page 9: Recursividade

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("\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

Page 10: Recursividade

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("\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

Page 11: Recursividade

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("\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

Page 12: Recursividade

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("\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:

Page 13: Recursividade

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("\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

Page 14: Recursividade

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("\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:

Page 15: Recursividade

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("\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

Page 16: Recursividade

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("\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!)

Page 17: Recursividade

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!

Page 18: Recursividade

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!

Page 19: Recursividade

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!

Page 20: Recursividade

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("\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

Page 21: Recursividade

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("\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

Page 22: Recursividade

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

Page 23: Recursividade

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!

Page 24: Recursividade

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!

Page 25: Recursividade

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("\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

Page 26: Recursividade

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("\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.

Page 27: Recursividade

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("\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

Page 28: Recursividade

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.

Page 29: Recursividade

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 ?

Page 30: Recursividade

Vamos ver um exemplo

int main(){exemplo(‘c’);return 0;

}

1

2

?

Passo 1: o programa se inicia.

Page 31: Recursividade

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

Page 32: Recursividade

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

Page 33: Recursividade

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

Page 34: Recursividade

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.

Page 35: Recursividade

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.

Page 36: Recursividade

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

Page 37: Recursividade

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

Page 38: Recursividade

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.

Page 39: Recursividade

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

Page 40: Recursividade

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

Page 41: Recursividade

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.

Page 42: Recursividade

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.

Page 43: Recursividade

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!

Page 44: Recursividade

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

Page 45: Recursividade

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?

Page 46: Recursividade

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.

Page 47: Recursividade

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.

Page 48: Recursividade

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!

Page 49: Recursividade

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.

Page 50: Recursividade

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.

Page 51: Recursividade

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

Page 52: Recursividade

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

Page 53: Recursividade

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

Page 54: Recursividade

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

Page 55: Recursividade

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

Page 56: Recursividade

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

Page 57: Recursividade

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

Page 58: Recursividade

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

Page 59: Recursividade

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

Page 60: Recursividade

Recursividade

Entender para onde voltar quando atingimos o caso base é essencial para conseguirmos entender o que é recursividade. Vamos ver uma mapa desta execução.

Page 61: Recursividade

RecursividadeNa primeira chamada tínhamos o seguinte passo recursivo:

1) 3 * fatorial(3-1)

Page 62: Recursividade

RecursividadeNa segunda chamada:

1) 3 * fatorial(3-1)

2) 2 * fatorial(2-1)

Page 63: Recursividade

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.

Page 64: Recursividade

RecursividadeLogo:

1) return 3 * fatorial(3-1)

2) return 2 * fatorial(2-1)

3) return 1

1

Page 65: Recursividade

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.

Page 66: Recursividade

RecursividadeLogo:

1) return 3 * fatorial(3-1)

2) return 23) return 1

2

Page 67: Recursividade

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!

Page 68: Recursividade

RecursividadeLogo:

1) return 62) return 2

3) return 1

6

Assim se encerra a nossa função recursiva!

Page 69: Recursividade

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

Page 70: Recursividade

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

Page 71: Recursividade

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!

Page 72: Recursividade

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.