Vous êtes sur la page 1sur 39

RECURSIVIDADE

A recursão é o processo pelo qual passa um certo


procedimento quando um dos passos do procedimento
em questão envolve a repetição completa deste
mesmo procedimento.

1 INF 01202 - Prof. Marcelo Walter – Aula 28


RECURSIVIDADE

Técnica de programação, na qual um subprograma


(função) chama a si mesmo.

Este exemplo é
apenas didático, não
void exemplo_recursao( int p ){ executa nada em
específico…
if (alguma condição de parada)
return;
else
exemplo_recursao(p-1);
}
2 INF 01202 - Prof. Marcelo Walter – Aula 28
RECURSIVIDADE

Nós já terminamos? Se sim, retorne os resultados.


Sem uma condição de parada como esta, uma
recursão iria se repetir eternamente.
Se não, simplifique o problema, resolva o(s)
problema(s) mais simples, e então encaixe os
resultados na solução do problema original. Então
retorne a solução.

3 INF 01202 - Prof. Marcelo Walter – Aula 28


RECURSIVIDADE

Todas as funções recursivas devem encerrar


(concluir) a recursão a partir de um teste de valor ou
condição!!!
SENÃO: laço infinito…

4 INF 01202 - Prof. Marcelo Walter – Aula 28


RECURSIVIDADE

Muitos problemas têm uma solução em programação


mais fácil, se resolvidos com recursão.

Você consegue pensar em algum exemplo que já vimos


em aula?

5 INF 01202 - Prof. Marcelo Walter – Aula 28


Fatorial de um número

5! = 5 * 4 * 3 * 2 * 1

Definição:
0! = 1;
n! = n * (n-1)!, para n > 0.

Definição recursiva: o fatorial de n é definido


em função do fatorial de (n-1)

6 INF 01202 - Prof. Marcelo Walter – Aula 28


Fatorial de um número – não recursivo
5! = 5 * 4 * 3 * 2 * 1
int fatorial (int n) // solução linear (NÃO-RECURSIVA)
{
int fat; // valor gerado
int aux; // variável auxiliar, para acumular o valor do fatorial

fat = 1;

for (aux = n; aux > 1; aux--)‫ ‏‬// se n=0 ou 1, não entra no for
{
fat = fat * aux ;
}

return fat; // encerra função, retornando valor


}

7 INF 01202 - Prof. Marcelo Walter – Aula 28


Fatorial de um número
5! = 5 * 4 * 3 * 2 * 1 = 5 * 4!
4!
4! = 4 * 3 * 2 * 1 = 4 * 3!

3!
3! = 3 * 2 * 1 = 3 * 2!

2!

se N = 0 (ou 1)
fatorial de n ← 1
senão
fatorial de n ← n * fatorial de n-1

8 INF 01202 - Prof. Marcelo Walter – Aula 28


Se N = 0 então Fatorial de N ← 1
Se N > 0 então
Fatorial de N ← N * fatorial de N-1

int fatorial (int n) // solução recursiva


{
int fat;
if (n < 1)
fat = 1; // encerra a recursão e inicia o retorno
else
fat = n * fatorial ( n - 1 ); // chamada recursiva
return fat; // retorna fatorial
}

9 INF 01202 - Prof. Marcelo Walter – Aula 28


Fatorial de um número: execução
fatorial(3) fatorial(2) fatorial(1) fatorial(0)

int main()‫‏‬ ←3*Fatorial (2) ← 2*Fatorial (1) ← 1*Fatorial (0) ←1


{

int f;
…; 6

f = fatorial(3);
printf(“%d”, f);
... 3*2

} 2*1
1*1
1

10 INF 01202 - Prof. Marcelo Walter – Aula 28


Execução de uma chamada de um subprograma recursivo

Início da execução
–  alocação de variáveis locais
–  parâmetros
Processamento
–  se a execução for interrompida por nova chamada
recursiva, ocorre o “empilhamento” dos indicadores de
execução atuais (valores, ponto de retorno)
Fim da execução
–  liberação de variáveis locais - “desempilhamento”
–  retorno ao ponto de chamada

11 INF 01202 - Prof. Marcelo Walter – Aula 28


r ()‫‏‬ r ()‫‏‬ r ()‫‏‬

int main( ) ... ...
scanf(“%d”,&m);
{ scanf(“%d”,&m); scanf(“%d”,&m);
// Lido:5
//Lido:7 //Lido:2
int k; … …

return(r()‫‏);‏‬ return(r()‫;)‏‬
… …
return(m);
end { r }; }
}

r 5 r 5 r 25
k=r();
printf(“%d”,k); L 7 L 2 L 5

} int r ()
{
int m;
k 5 printf(“informe valor:”);
scanf(“%d”,&m);
k if (m!= 5)
return r();
else
return m;
12
}
INF 01202 - Prof. Marcelo Walter – Aula 28
Exemplos de outros problemas recursivos

•  soma de números inteiros de A a B


• A + (soma dos números inteiros de A+1 a B)
• A+1 + (soma dos números inteiros de A+2 a B)
•  até que a soma de As fique igual a B. Neste
momento a soma é o próprio B e podemos retornar

•  Exemplo: A=2, B=5


•  2+ soma(3,5) Condição de parada! O
intervalo de soma tem apenas
•  3 + soma(4,5) um número
•  4 + soma(5,5)
•  4 + 5 = 9
•  3 + 9
•  2 + 12
•  14
13 INF 01202 - Prof. Marcelo Walter – Aula 28
Exercício: fazer um programa contendo uma função que calcula a soma dos n
elementos inteiros de um vetor, de forma recursiva. No programa principal,
ler os números e informar a soma.


#define N 10
int soma_rec (int v[ ], int ultimo)
{
if (ultimo == 0)
return v[0];
else
return v[ultimo] + soma_rec (v, ultimo - 1);
}
int main (void)
{
int numeros[N];
int i;
for (i = 0; i < N; i++)
scanf ("%d", &numeros[i]); // lê valores: incluir printf explicativo

printf("soma dos valores lidos eh %d", soma_rec(numeros, N-1) );

return 0;
}
14 INF 01202 - Prof. Marcelo Walter – Aula 28
Exercício: fazer um programa contendo uma função que calcula a soma dos n
elementos inteiros de um vetor, de forma recursiva. No programa principal,
ler os números e informar a soma.


#define N 10
int soma_rec (int v[ ], int ultimo)
{
if (ultimo == 0)
return v[0];
else
return v[ultimo] + soma_rec (v, ultimo - 1);
}
int main (void)
{
int numeros[N];
int i;
for (i = 0; i < N; i++)
scanf ("%d", &numeros[i]); // lê valores: incluir printf explicativo

printf("soma dos valores lidos eh %d", soma_rec(numeros, N-1) );

return 0;
}
15 INF 01202 - Prof. Marcelo Walter – Aula 28
Série de Fibonacci

Descoberta por Leonardo Pisano - 1202

+ +
1 1 2 3 5 8 13 21 34 55…
fib(1) = 1
fib(2) = 1
fib(n) = fib(n-1) + fib(n-2), para n > 2 55

34
16 INF 01202 - Prof. Marcelo Walter – Aula 28
Cálculo do nésimo termo – NÃO
RECURSIVO (já visto em aula)
int fib (int n) // devolve apenas o nésimo termo
{
// devolve o termo n da série de Fibonacci
int i;
int fibn, fibn_1 = 0, fibn_2 =1; //termos fib(n), fib(n-1) e fib(n-2))
for (i=1; i <= n; i++)
{ //calcula TODOS os termos, inclusive os 2 primeiros:
fibn = fibn_2 + fibn_1;
fibn_2 = fibn_1; //atualiza os antecessores na série
fibn_1 = fibn;
}
return fibn; /* retorna o termo solicitado*/
}

17 INF 01202 - Prof. Marcelo Walter – Aula 28


Série de Fibonacci

1 1 2 3 5 8 13 ...
FIB (5)‫? ‏‬

fib(1) = 1
fib(2) = 1
fib(n) = fib(n-1) + fib(n-2), para n > 2

recursão!

18 INF 01202 - Prof. Marcelo Walter – Aula 28


Série de Fibonacci
1 1 2 3 5 8 13 ...
FIB ( 5 )

FIB ( 4 ) + FIB ( 3 )

FIB ( 3 ) + FIB ( 2 ) FIB ( 2 ) + FIB ( 1 )

1 1 1
FIB ( 2 ) + FIB ( 1 )

1 1

19 INF 01202 - Prof. Marcelo Walter – Aula 28


Série de Fibonacci

1 1 2 3 5 8 13 ... fib (5)‫?‏‬

int fib(int n) // solução recursiva


{
/* devolve o termo n da série de fibonacci */
if (n < 3) // 10 e 20 termo = 1
return 1;
else
return fib(n-1) + fib(n-2);
}

20 INF 01202 - Prof. Marcelo Walter – Aula 28


Série de Fibonacci
FIB ( 5 )

FIB ( 4 ) + FIB ( 3 )

FIB ( 3 ) + FIB ( 2 ) FIB ( 2 ) + FIB ( 1 )

FIB ( 2 ) + FIB ( 1 )

21 INF 01202 - Prof. Marcelo Walter – Aula 28


Série de Fibonacci

FIB ( 5 )

FIB ( 4 ) + FIB ( 3 )

FIB ( 3 ) + FIB ( 2 ) FIB ( 2 ) + FIB ( 1 )

FIB ( 2 ) + FIB ( 1 )
redundância!

22 INF 01202 - Prof. Marcelo Walter – Aula 28


Vantagens da Recursividade
•  código mais compacto;
•  especialmente conveniente para estruturas
de dados definidas recursivamente, tais
como árvores;
•  código pode ser mais fácil de entender.

Desvantagens da Recursividade
•  maior ocupação de memória;
•  maior tempo de processamento.

23 INF 01202 - Prof. Marcelo Walter – Aula 28


Recursividade

void rec (x)


{
è  chamada condicional …
(condição de fim da if …
recursão)‫‏‬ return val;
...

è  cada chamada ativa uma rotina no stack

è  sempre pode ser substituído por programação


com comandos iterativos

24 INF 01202 - Prof. Marcelo Walter – Aula 28


O que faz?
#include <stdio.h> int main (void)
#include <ctype.h> {
int i,n;
void nome(int i, int n) char opc;
do
{
{
if (i < n) printf("Entre os valores dos numeros:\n");
{ scanf("%d%d", &i, &n);
printf("Execucao da funcao 'nome': \n");
printf(“%d\n”, i ); nome(i,n);
nome( i + 2, n ); printf("Executar novamente (S/N)?\n");
} scanf(” %c", &opc);
} while ( toupper(opc)!='N');
else
{ return 0;
printf(“%d\n”, i ); }

}
}

25 INF 01202 - Prof. Marcelo Walter – Aula 28


26 INF 01202 - Prof. Marcelo Walter – Aula 28
O que muda se inverter a ordem dos 2 comandos abaixo?
Somente executa a
impressão após as
chamadas recursivas
void nome(int i, int n) int main (void)
{ {
int i,n;
if (i < n) char opc;
{ do
{
nome( i + 2, n ); printf("Entre os valores dos numeros:\n");
printf(“%d\n”, i ); scanf("%d%d", &i, &n);
printf("Execucao da funcao 'nome': \n");
} nome(i,n);
else printf("Executar novamente (S/N)?\n");
fflush(stdin);
{ scanf("%c", &opc);
printf(“%d\n”, i ); } while ( toupper(opc)!='N');
} return 0;
} }

27 INF 01202 - Prof. Marcelo Walter – Aula 28


O que muda se inverter a ordem dos 2 comandos abaixo?

28 INF 01202 - Prof. Marcelo Walter – Aula 28


O que faz a subrotina abaixo?
int p ( int x, int y) p(1,4)=?
{
if ( x = = y)
p ( 1, 4 )
return y;
else 4+p(1,3)
return y + p ( x , y - 1 ); 3+p(1,2)

} 2+p(1,1)
1

p ( 7, 3 ) = 10
p(7,3)=?
3+p(7,2) CUIDADO! Recursão
infinita se y < x
2+p(7,1)
1+p(7,0)
29 .......
INF 01202 - Prof. Marcelo Walter – Aula 28
O que faz a subrotina abaixo?
void rv( ) ?
{ ABC#
char ch;
scanf(“%c”, &ch);
if (ch != ´#´)
rv(); ABC# #CBA
#
#CB
#C
printf(“%c”, ch);
}

C A C B C C C #

30 INF 01202 - Prof. Marcelo Walter – Aula 28


Recursividade mútua
float g ( float x); // protótipo

float f ( float x)
resul = f(3); ?
{
if (x == 0)
return 0; f (3)
else 3 + g (3)
return x + g (x); 4 - f (2)
} 2 + g (2)
4 - f (1)
float g ( float x) 1 + g (1)
{ 4 - f (0)
return 4 - f ( x - 1 ); 0
} 333+++44
34---(2
(2
(2
1 +++4344
2---(1
(1
1
5 ++44--0))
0))↔== 666

31 INF 01202 - Prof. Marcelo Walter – Aula 28


Exercício: escrever uma função recursiva que testa se uma
palavra é palíndroma

REVIVER

Ideia: comparar a primeira e a última


letra: se forem iguais, testar a
substring do meio, recursivamente.

Se não forem iguais, então encerra.

32 INF 01202 - Prof. Marcelo Walter – Aula 28


Escrever uma função recursiva que testa se uma palavra é
palíndroma

REVIVER Removemos 2
caracteres: o
primeiro e o
último

strncpy (s1, &s[1], strlen(s) - 2);

quantos caracteres

copiar de onde (a partir do 2o char)‫‏‬

para onde (qual string)

33 INF 01202 - Prof. Marcelo Walter – Aula 28


int palindroma (char s[ ]) // retorna 1, se a string "s" for palindroma, ou 0, se não for
{
char s1[strlen(s)-2]; // define outra string, que recebera a parte central de "s"
int eh_palind; // saida da funcao
if (s[0] == s[strlen(s)-1]) // compara a primeira e ultima letras
{
if (( strlen(s) == 1 ) || ( strlen(s) == 2)) // se a string tiver 1 ou 2 letras, retorna 1
eh_palind = 1;
else
{
/* monta uma nova string tirando os 2 extremos */
strncpy (s1, &s[1], strlen(s) - 2);
s1[strlen(s) - 2] = '\0'; // coloca o simbolo de final de string
/* chamada recursiva para a substring central */
eh_palind = palindroma (s1);
}
}
else // retorna zero se o teste falhar para alguma substring
eh_palind = 0;
return eh_palind;
}

34 INF 01202 - Prof. Marcelo Walter – Aula 28


int main (void)
{
char str[40];
gets(str);
if (palindroma(str)==1)
printf("%s eh palindroma\n", str);
else
printf("%s NAO eh palindroma\n", str);

return 0;
}

35 INF 01202 - Prof. Marcelo Walter – Aula 28


Exemplo

ü  Escreva uma função recursiva

int func_soma(int n)

que recebe como entrada um número n par ou impar.


Se n for par, a função deve retornar o valor 0 + 2 + 4
+ ... + n, e se n for ímpar, a função deve retornar 1 + 3
+ 5 + ... + n.

36 INF 01202 - Prof. Marcelo Walter – Aula 28


Solução
#include <stdio.h>
#include <string.h> int main()
{int n;
int func_soma(int n) printf("Digite um nro inteiro: ");
{ scanf("%d",&n);
if (n == 0) return 0; printf("A soma dos elementos eh %d
\n”, func_soma(n));
else if (n==1) return 1;
else return n+func_soma(n-2); return 0;
}
}

37 INF 01202 - Prof. Marcelo Walter – Aula 28


Exemplos de outros problemas recursivos

• encontrar elemento numa lista: examinar um


elemento e examinar resto da lista (até lista vazia)‫‏‬

• inverter uma lista: trocar os dois extremos, e


inverter o restante da lista

• ordenar arranjo: colocar o menor elemento na


primeira posição e ordenar o restante do arranjo
(algoritmo no próximo slide)

38 INF 01202 - Prof. Marcelo Walter – Aula 28


Exercício: o método de ordenação por seleção consiste em identificar o menor
elemento, colocar este elemento na 1a posição e repetir o processo para os
demais elementos.
Faça o algoritmo e o programa que implemente este método, composto por uma
função recursiva ordena, uma função pos_menor que retorna a posição do
menor elemento de um vetor (vetor, posição inicial de busca e posição final de
busca devem ser passados como parâmetro) e uma função troca que inverte o
conteúdo de 2 variáveis passadas como parâmetros. No programa principal,
incluir a leitura de um vetor de 10 elementos reais, a chamada da função
ordena e a impressão do vetor classificado.

Algoritmo Ordena_Selecao;
{ordena vetores pelo método de seleção}
Entrada: vetor;
Saída: vetor classificado em ordem crescente;
1. Inicio
2. Para (ind ← 1;ind < num_elem; ind++)
lê vetor[ind]
3. Ordena(vetor,pos_inic, pos_fim) {função}
4. Para (ind ← 1;ind < num_elem; ind++)
imprime vetor[ind]
5 Fim.

39 INF 01202 - Prof. Marcelo Walter – Aula 28

Vous aimerez peut-être aussi