40
Recursividade Prof. Gláucya Boechat [email protected]

Recursividade - UNICAMPglaucya/ifsp/EDI/EDI_Recursividade.pdf · Algoritmo 1.Comece com qualquer triângulo em um plano. O triângulo de ... Cada disco só pode ser colocado em uma

Embed Size (px)

Citation preview

Recursividade

Prof. Gláucya [email protected]

2

RecursividadeRecursividade

● A recursão é uma técnica que define um problema em termos de uma ou mais versões menores deste mesmo problema.

● É um princípio que permite obter a solução de um problema a partir do próprio problema.

● Exemplos– Dois espelhos são apontados um para o outro,

– Caracóis, girassóis, folha de algumas árvores

3

ExemplosExemplos

4

Bonequinhas RussasBonequinhas Russas

5

Triângulo de Sierpinski Triângulo de Sierpinski● Figura geométrica obtida através de um processo recursivo

6

Triângulo de Sierpinski Triângulo de Sierpinski● Algoritmo

1. Comece com qualquer triângulo em um plano. O triângulo de Sierpinski canônico utilizava um triângulo equilátero (figura a.).

2. Encolha o triângulo pela metade (cada lado deve ter metade do tamanho original), faça três copias, e posicione cada triângulo de maneira que encoste nos outros dois em um canto (figura b.).

3. Repita o passo 2 para cada figura obtida, indefinidamente (a partir da figura c.).

7

Estrutura recursivaEstrutura recursiva

● Diz-se que uma estrutura é recursiva se a forma do todo se repete na forma das partes.

8

Função recursivaFunção recursiva

● Uma função recursiva é a capacidade de uma função chamar a própria função.– Exemplo (fatorial)

n! = n(n­1)!

● Quando uma função recursiva chama a si mesma, uma nova cópia da função passa a ser executada.

– Os parâmetros locais da segunda cópia são independentes dos parâmetros locais da primeira.

– Exemplos● Números naturais, função fatorial, árvores

9

TiposTipos

● Recursão direta ou simples– Quando a função recursiva chama a si mesma

diretamente.

● Recursão indireta ou composto – Quando a função chama outra função, e esta, por

sua vez chama a primeira.

10

Torres de HanóiTorres de Hanói● Quebra-cabeça inventado no ano de 1883, pelo

matemático Eduard Lucas.

● Objetivo

– Transferir os oito discos que formam a torre para um dos dois bastões vazios, repeitando as seguintes regras:

● Mover apenas um único disco de cada vez;● Nunca colocar um disco maior sobre um disco menor;● Cada disco só pode ser colocado em uma das três hastes.

11

Torres de HanóiTorres de Hanói

● Solução do problema com uma torre de quatro discos

12

Solução recursivaSolução recursiva● Para resolver um jogo onde precisamos mover n

discos, considerando n > 1, podemos executar os seguintes passos:– Mova n-1 discos para o “pino de trabalho”.

– Mova o n-ésimo pino (o maior de todos) do “pino origem” para o “pino destino”.

– Em seguida resolva o problema da “Torre de Hanói” para os n-1 discos dispostos no “pino de trabalho”, movendo-os para o “pino destino” utilizando o mesmo princípio.

13

Jogo com 3 discosJogo com 3 discos

● Passo 1● Transferência de n-1 discos do “pino origem” para o

“pino de trabalho. – Nesta caso, “pino destino” atua como auxiliar.

– Movimento 1● Pino Origem → Pino Destino

14

Jogo com 3 discosJogo com 3 discos

● Passo 1– Movimento 2

● Pino Origem-> Pino Trabalho

15

Jogo com 3 discosJogo com 3 discos

● Passo 1– Movimento 3

● Pino Destino-> Pino Trabalho

16

Jogo com 3 discosJogo com 3 discos

● Passo 2● Transferência do maior disco do “pino origem” para o

“pino destino”

– Movimento 4● Pino Origem-> Pino Destino

17

Jogo com 3 discosJogo com 3 discos

● Passo 3– Transferência dos n-1 discos do “pino de trabalho”

para o “pino destino”. ● Desta vez, o “pino de origem” atua como área de

armazenamento auxiliar

– Movimento 5● Pino Trabalho-> Pino Origem

18

Jogo com 3 discosJogo com 3 discos

● Passo 3– Movimento 6

● Pino Trabalho-> Pino Destino

19

Jogo com 3 discosJogo com 3 discos

● Passo 3– Movimento 7

● Pino Origem-> Pino Destino

20

FibonacciFibonacci

● Caso base

Fib(0) = 1 se n = 0

Fib(1) = 1 se n = 1

● Recursão

Fib(n) = Fib(n-2)+Fib(n-1) se n > 1

21

Estrutura de uma recursãoEstrutura de uma recursão

● Função(lista de parâmetros)– Caso base (Condição de parada)

● Teste de término de recursão– Se teste ok, retorna aqui

● Pode existir mais de um caso base.

– Caso recursivo (Regra geral) ● É a alma da recursão● Permite ao programador redefinir o problema para um que

se aproxime mais do caso base

22

Condição de paradaCondição de parada

● Em funções recursivas pode ocorrer um problema de terminação do programa,– Como um loop interminável ou infinito

● Para não gerar uma recursão infinita, é necessário criar uma condição de parada,– Ela vai dizer quando a função deverá parar de

chamar instâncias dela

23

Passo básicosPasso básicos

1.Inicializar o algoritmo.

● Comece com um ponto de partida, normalmente é passado por parâmetro;

2. Verificar se o valor avaliado corresponde ao caso base;

3. Redefine a resposta em um subproblema menor;

4. Rode o algoritmo no subproblema definido;

5. Combina o resultado para formular a resposta;

6. Devolve um resultado.

24

FatorialFatorial

n! = n.(n – 1).(n – 2). … .1

int fatorial(int n){ int fat = n; while(n>1){

fat=fat*--n;}

return fat;}

25

FatorialFatorial

● Recursiva

int fatorial (int n){ if(n==0) return 1; return n*fatorial(n-1); }

n! =1, se n=0 n(n-1)!, se n>0

26

FatorialFatorial● Exemplo 4!

fatorial(4)int fatorial (int n){ if(n==0) return 1; return n*fatorial(n-1); }

4*fatorial(3)

n! =1, se n=0 n(n-1)!, se n>0

27

FatorialFatorial● Exemplo 4!

fatorial(4)int fatorial (int n){ if(n==0) return 1; return n*fatorial(n-1); }

4*fatorial(3)

3*fatorial(2)

n! =1, se n=0 n(n-1)!, se n>0

28

FatorialFatorial● Exemplo 4!

fatorial(4)int fatorial (int n){ if(n==0) return 1; return n*fatorial(n-1); }

4*fatorial(3)

3*fatorial(2)

2*fatorial(1)

n! =1, se n=0 n(n-1)!, se n>0

29

FatorialFatorial● Exemplo 4!

fatorial(4)int fatorial (int n){ if(n==0) return 1; return n*fatorial(n-1); }

4*fatorial(3)

3*fatorial(2)

2*fatorial(1)

1*fatorial(0)

n! =1, se n=0 n(n-1)!, se n>0

30

FatorialFatorial● Exemplo 4!

fatorial(4)int fatorial (int n){ if(n==0) return 1; return n*fatorial(n-1); }

4*fatorial(3)

3*fatorial(2)

2*fatorial(1)

1*fatorial(0)

1

n! =1, se n=0 n(n-1)!, se n>0

31

FatorialFatorial● Exemplo 4!

fatorial(4)int fatorial (int n){ if(n==0) return 1; return n*fatorial(n-1); }

4*fatorial(3)

3*fatorial(2)

2*fatorial(1)

1*fatorial(0)

1

n! =1, se n=0 n(n-1)!, se n>0

32

FatorialFatorial● Exemplo 4!

fatorial(4)int fatorial (int n){ if(n==0) return 1; return n*fatorial(n-1); }

4*fatorial(3)

3*fatorial(2)

2*fatorial(1)

1*1

n! =1, se n=0 n(n-1)!, se n>0

33

FatorialFatorial● Exemplo 4!

fatorial(4)int fatorial (int n){ if(n==0) return 1; return n*fatorial(n-1); }

4*fatorial(3)

3*fatorial(2)

2*1

n! =1, se n=0 n(n-1)!, se n>0

34

FatorialFatorial● Exemplo 4!

fatorial(4)int fatorial (int n){ if(n==0) return 1; return n*fatorial(n-1); }

4*fatorial(3)

3*2

n! =1, se n=0 n(n-1)!, se n>0

35

FatorialFatorial● Exemplo 4!

n! =1, se n=0 n(n-1)!, se n>0

fatorial(4)=int fatorial (int n){ if(n==0) return 1; return n*fatorial(n-1); }

4*6=24

36

Algoritmo de EuclidesAlgoritmo de Euclides

mdc(a: inteiro; b: inteiro): inteiroinício se b = 0 então return a senão return mdc(b, a mod b) fim-sefim-função

37

Recursividade indiretaAlgoritmo de EuclidesRecursividade indiretaAlgoritmo de Euclides

int mdc1(int valorA, int valorB){ printf("\nMDC 1\n"); if(!valorB) return valorA; else return mdc2(valorB, valorA%valorB);}

int mdc2(int valorA, int valorB){ printf("\nMDC 2\n"); if(!valorB) return valorA; else return mdc1(valorB, valorA%valorB);}

38

Recursividade indiretaAlgoritmo de EuclidesRecursividade indiretaAlgoritmo de Euclides

mdc2(valorB, valorA%valorB)

mdc1(valorB, valorA%valorB)

mdc1

mdc2

39

VantagensVantagens

● Soluções recursivas são, geralmente, mais elegantes que suas contrapartes iterativas.

● Uma função recursiva é menor que sua versão iterativa.

40

DesvantagensDesvantagens

● Recursão é lenta:

– Ao chamar uma função, precisamos copiar os parâmetros e inicializar as variáveis. Isso demanda tempo.

● Recursões grandes consomem uma grande quantidade de memória,

– pois é necessário guardar o estado das funções que estão esperando a próxima retornar

● Um deslize na definição da condição de parada pode fazer seu programa chamar a função infinitamente.

– Sempre se assegure que há uma condição de parada