• Nenhum resultado encontrado

Pensamento Recursivo. O Objeto Carro. O Objeto Carro. O Objeto Carro. O Objeto Carro. O Objeto Carro

N/A
N/A
Protected

Academic year: 2021

Share "Pensamento Recursivo. O Objeto Carro. O Objeto Carro. O Objeto Carro. O Objeto Carro. O Objeto Carro"

Copied!
9
0
0

Texto

(1)

1

1

Ë Esta seção introduz a técnica de

programação recursiva.

Ë Como você sabe, programação

recursiva envolve ocorrências menores do mesmo problema.

Pensamento Recursivo

Prof. Dr. José Augusto Baranauskas

2

O Objeto Carro

Ë Para iniciar o exemplo,

pense em seu carro favorito.

3

O Objeto Carro

Ë Para iniciar o exemplo,

pense em seu carro favorito.

4

O Objeto Carro

Ë Para iniciar o exemplo,

pense em seu carro favorito.

5

O Objeto Carro

Ë Para iniciar o exemplo,

pense em seu carro favorito.

6

O Objeto Carro

Ë Para iniciar o exemplo,

pense em seu carro favorito.

Ë Imagine que o carro é

(2)

2

7

O Objeto Carro

struct Car { . . . };

Ë Para iniciar o exemplo,

pense em seu carro favorito.

Ë Imagine que o carro é

controlado por um sinal de rádio vindo de um computador.

Ë Os sinais de rádio são

gerados ativando-se os procedimentos de um

Carro. 8

struct Car

{ // Nós não precisamos saber sobre campos!

. . .

};

void MakeConnection(Car C, int CarNumber); void Move(Car C);

void TurnAround(Car C); boolean Blocked(Car C);

Procedimentos para o Objeto Carro

9 int main { Car Racer; MakeConnection(Racer,7); . . . }

Exemplos de Chamada de

Procedimento

Quando nós ativamos MakeConnection, o computador faz uma conexão ou link com o carro que tem um número exclusivo. 10 int main { Car Racer; MakeConnection(Racer,7); TurnAround(Racer); . . . }

Exemplos de Chamada de

Procedimento

Quando nós ativamos TurnAround, o sinal do computador avisa o carro para virar 180 graus.

(3)

3

13 int main { Car Racer; MakeConnection(Racer,7); TurnAround(Racer); Move(Racer); if (Blocked(Racer)) cout << ”Impossível mover!";

. . .

}

Exemplos de Chamada de

Procedimento

O método Blocked é uma função que detecta barreiras.

14

Sua Missão

Ë Escreva um procedimento que mova um carro para a

frente até que ele encontre uma barreira ...

15

Sua Missão

Ë Escreva um procedimento que mova um carro para a

frente até que ele encontre uma barreira ...

16

Sua Missão

Ë Escreva um procedimento que mova um carro para a

frente até que ele encontre uma barreira ...

17

Sua Missão

Ë Escreva um procedimento que mova um carro para a

frente até que ele encontre uma barreira ...

Ë ... então o carro é virado novamente...

18

Sua Missão

Ë Escreva um procedimento que mova um carro para a

frente até que ele encontre uma barreira ...

Ë ... então o carro é virado novamente...

Ë ...e retorna à sua posição inicial percorrendo o caminho

(4)

4

19

Sua Missão

Ë Escreva um procedimento que mova um carro para a

frente até que ele encontre uma barreira ...

Ë ... então o carro é virado novamente...

Ë ...e retorna à sua posição inicial percorrendo o caminho

oposto.

20

Sua Missão

Ë Escreva um procedimento que mova um carro para a

frente até que ele encontre uma barreira ...

Ë ... então o carro é virado novamente...

Ë ...e retorna à sua posição inicial percorrendo o caminho

oposto.

void Ricochet(Car MovingCar);

MovingCar

21

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

void Ricochet(Car MovingCar);

22

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

Move(MovingCar);

. . .

void Ricochet(Car MovingCar);

23

void Ricochet(Car MovingCar);

Move(MovingCar);

. . .

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

Isso torna o problema um

pouco menor. Por exemplo,

se o carro começar a uma distância de 100 metros da barreira ...

100 metros

24

void Ricochet(Car MovingCar);

Move(MovingCar);

. . .

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

Isso torna o problema um

pouco menor. Por exemplo,

se o carro começar a uma distância de 100 metros da barreira ... então após ativar Move um vez, a distância passa a ser 99 metros.

(5)

5

25

void Ricochet(Car MovingCar);

Move(MovingCar);

. . .

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

Agora nós temos

uma versão menor

deste mesmo

problema.

99 metros

26

void Ricochet(Car MovingCar);

Move(MovingCar); Ricochet(MovingCar);

. . .

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

Faça uma chamada

recursiva para

resolver o pequeno

problema ...

99 metros

27

void Ricochet(Car MovingCar);

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

A chamada

recursiva resolverá o

problema.

99 metros Move(MovingCar); Ricochet(MovingCar); . . . 28

void Ricochet(Car MovingCar);

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

A chamada

recursiva resolverá o

problema.

Move(MovingCar); Ricochet(MovingCar); . . . 29

void Ricochet(Car MovingCar);

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

A chamada

recursiva resolverá o

problema.

Move(MovingCar); Ricochet(MovingCar); . . . 30

void Ricochet(Car MovingCar);

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

(6)

6

31

void Ricochet(Car MovingCar);

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

A chamada

recursiva resolverá o

problema.

Move(MovingCar); Ricochet(MovingCar); . . . 32

void Ricochet(Car MovingCar);

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

A chamada

recursiva resolverá o

problema.

Move(MovingCar); Ricochet(MovingCar); . . . 33

void Ricochet(Car MovingCar);

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

A chamada

recursiva resolverá o

problema.

Move(MovingCar); Ricochet(MovingCar); . . . 34

void Ricochet(Car MovingCar);

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

A chamada

recursiva resolverá o

problema.

Move(MovingCar); Ricochet(MovingCar); . . . 35

void Ricochet(Car MovingCar);

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

A chamada

recursiva resolverá o

problema.

Move(MovingCar); Ricochet(MovingCar); . . . 36

void Ricochet(Car MovingCar);

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

(7)

7

37

void Ricochet(Car MovingCar);

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

Qual é o último passo

necessário para

retornar à nossa

posição original?

99 metros Move(MovingCar); Ricochet(MovingCar); . . . 38

void Ricochet(Car MovingCar);

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com:

100 metros

Qual é o último passo

necessário para

retornar à nossa

posição original?

Move(MovingCar); Ricochet(MovingCar); Move(MovingCar); 39

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com: Este procedimento recursivo segue um padrão comum que você deve reconhecer.

Move(MovingCar); Ricochet(MovingCar); Move(MovingCar);

void Ricochet(Car MovingCar);

40

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com: Quando o problema é simples, resolva-o sem chamadas recursivas. Este é o caso base. Move(MovingCar); Ricochet(MovingCar); Move(MovingCar);

void Ricochet(Car MovingCar);

41

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com: Quando o problema é mais complexo, comece criando uma versão

menor do mesmo problema... Move(MovingCar);

Ricochet(MovingCar); Move(MovingCar);

void Ricochet(Car MovingCar);

42

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com: ...e uma chamada

recursiva para resolver

totalmente o problema menor...

Move(MovingCar); Ricochet(MovingCar); Move(MovingCar);

(8)

8

43

Pseudo-código para Ricochet

‚ Se Blocked(MovingCar) é verdadeiro, então o carro

está próximo à barreira. Neste caso, apenas vire o carro.

ƒ Caso contrário, o carro ainda não chegou na barreira,

então comece com: ... e finalmente faça quaisquer operações que sejam necessárias para completar a solução do problema original Move(MovingCar); Ricochet(MovingCar); Move(MovingCar);

void Ricochet(Car MovingCar);

44

Implementação de Ricochet

void Ricochet(Car MovingCar) {

if (Blocked(MovingCar)) // caso base TurnAround(MovingCar);

else // caso recursivo { Move(MovingCar); Ricochet(MovingCar); Move(MovingCar); } } 45

Um Exercício

Escreva um procedimento Escreva um procedimento

recursivo para calcular o

recursivo para calcular o

fatorial de um número

fatorial de um número

inteiro. Lembre

inteiro. Lembre--se:se: 0! = 1! = 1

0! = 1! = 1

n! = n * (n

n! = n * (n--1)!, se n > 11)!, se n > 1

Você tem 2 minutos para escrever a declaração. int fatorial(int n) { } 46

Um Exercício

int fatorial(int n) { if (n <= 1) // caso base return 1;

else // caso recursivo return n * fatorial(n-1); }

Uma Solução Recursiva

47

Outro Exercício

Escreva um procedimento

Escreva um procedimento

não

nãorecursivo para calcular o recursivo para calcular o

fatorial de um número inteiro.

fatorial de um número inteiro.

Lembre

Lembre--se:se:

0! = 1! = 1

0! = 1! = 1

n! = n * (n

n! = n * (n--1)!, se n > 11)!, se n > 1

Você tem 3 minutos para escrever a declaração. int fatorial(int n) { } 48

Outro Exercício

int fatorial(int n) { int i, produto = 1; for (i = 2; i <= n; i++) produto *= i; return produto; }

(9)

9

49

Um Desafio

Um algoritmo muito conhecido para determinar o maior divisor comum de dois inteiros é o algoritmo de Euclides

Escreva um procedimento

Escreva um procedimento recursivorecursivoe e

outro

outro não recursivonão recursivopara calcular o MDCpara calcular o MDC MDC(n,m) se n > m MDC(n,m) se n > m MDC(m,n) = m se n = 0 MDC(m,n) = m se n = 0 MDC(n, m % n) se n > 0 MDC(n, m % n) se n > 0

Você tem 5 minutos para escrever a declaração.

{

50

Um Desafio

int mdc(int m, int n) {

if (n == 0) // caso base return m;

else // caso recursivo if (n > m) return mdc(n,m); else if (n > 0) return mdc(n, m % n); }

Uma Solução Recursiva

51

Um Desafio

int mdc(int m, int n) {

?

}

Uma Solução Não Recursiva

Para a solução não recursiva deste problema, você precisa conhecer o TAD pilha!

52

Ë

Ë Recursão é um recurso útil quando o problema a ser Recursão é um recurso útil quando o problema a ser

solucionado é definido de forma recursiva

solucionado é definido de forma recursiva

Ë

Ë Programas recursivos são Programas recursivos são eleganteselegantesna sua definição, na sua definição,

expressando concisamente o problema em termos de

expressando concisamente o problema em termos de

subproblemas

subproblemas

Ë

Ë Todo programa recursivo pode ser escrito de forma não Todo programa recursivo pode ser escrito de forma não

recursiva (iterativa) e vice

recursiva (iterativa) e vice--versaversa

Ë

Ë Nos casos mais complexos, para transformar um programa Nos casos mais complexos, para transformar um programa

recursivo num não recursivo é necessário o uso do TAD pilha

recursivo num não recursivo é necessário o uso do TAD pilha

Ë

Ë O uso da recursão em problemas inerentemente iterativos pode O uso da recursão em problemas inerentemente iterativos pode

gerar programas ineficientes

gerar programas ineficientes

Resumo

53

THE END

Presentation copyright 1995, The Benjamin/Cummings Publishing Company, For use with Data Structures and Other Objects

by Michael Main and Walter Savitch.

Some artwork in the presentation is used with permission from Presentation Task Force (copyright New Vision Technologies Inc) and Corel Gallery Clipart Catalog (copyright Corel Corporation, 3G Graphics Inc, Archive Arts, Cartesia Software, Image Club Graphics Inc, One Mile Up Inc, TechPool Studios, Totem Graphics Inc). Students and instructors who use Data Structures and Other Objects are welcome to use this presentation however they see fit, so long as this copyright notice remains intact.

Referências

Documentos relacionados

MCD com Generalização-Especialização Exemplo: CARRO CARRO CORRIDA CARRO OFICIAL CARRO PARTICULAR C C CARRO OFICIAL FEDERAL CARRO OFICIAL ESTADUAL é feito FABRICANTE 1,N 1,1 parti

[r]

Não existe cura para a DP, entretanto, intervenções podem melhorar os sintomas e diminuir a velocidade de destruição da doença, bem como proporcionar uma qualidade de

Neste contexto, o objetivo deste estudo foi investigar a regeneração química do carvão de ossos bovinos, saturado com orgânicos refratários de efluente concentrado salino

Nesse sentido, o objetivo deste trabalho foi realizar o mapeamento de cana-de-açúcar no município de Mirante do Paranapanema-SP utilizando imagens do satélite sino-brasileiro

a) a colocação de crianças em escolas especiais ou em salas especiais nas escolas regulares de forma permanente deverá ser considerada medida excepcional,

Os resultados obtidos nas comparações dos ní- veis de exigência e responsividade atribuídos a pais e mães seguiram um padrão já observado em outros estudos (Costa, Teixeira

(Prova + Pré-Projeto de Tese e CV Lattes + Defesa Oral do Pré-Projeto de Tese) / 3 = Nota Final 7.5 Para a concessão das bolsas previstas neste Edital, o candidato deve ter