Introdução à Programação
Recursão
Tópicos da Aula
Hoje, aprenderemos a usar uma técnica de
programação chamada de recursão
Conceito de Recursão
Definições Recursivas
Casos Base e Geral
Programando Recursivamente
Recursão X Laço
2
Recursão
Uma definição recursiva de um conceito consiste em
utilizar o próprio conceito na definição
Ex: fat(n) = n * fat(n-1)
Definições recursivas em linguagem natural não são,
geralmente, muito úteis
Contudo, em outras situações, uma definição recursiva
pode ser a mais apropriada para explicar um conceito
Recursão é uma técnica de programação que pode
fornecer soluções elegantes para determinados
problemas
Mas, antes, deve-se aprender a pensar
recursivamente!
3
Definições Recursivas: Lista
Considere a seguinte lista de números
24, 88, 40, 37
Podemos definir uma lista de números como:
Uma LISTA é um: número
ou um: número
vírgula
LISTA
Resumindo: uma LISTA é definida ou como um
único número, ou como um número seguido de
uma vírgula seguida de uma LISTA
Utilizamos LISTA para sua própria definição
4
Definições Recursivas: Lista
A parte recursiva da definição de LISTA é
utilizada diversas vezes, até que se possa
utilizar a parte não recursiva
número vírgula
24
,
LISTA
88, 40, 37
88 , 40, 37
Parte não
recursiva da
definição de
LISTA
Parte
recursiva da
definição de
LISTA
40, 37
37
5
Definições Recursivas: Fatorial
Fatorial de um número N (N!), que é inteiro e
positivo, é definido como a multiplicação de
todos os inteiros compreendidos entre 1 e N
(inclusive)
Podemos definir fatorial recursivamente:
0! = 1
N! = N x (N-1)!
Mais uma vez, utilizamos fatorial para sua
própria definição
6
Definições Recursivas: Fatorial
5!
120
5 * 4!
24
4 * 3!
6
3 * 2!
2 * 1!
1 * 0!
1
2
1
7
Caso Base e Caso Geral
Toda definição recursiva deve ter uma parte
recursiva e outra não recursiva
Se não houver a parte não recursiva, o
caminho recursivo nunca termina
Gera uma recursão infinita
Similar a um laço infinito
Denomina-se de caso base, a parte não
recursiva da definição, enquanto o caso geral
é a parte recursiva
8
Definições Recursivas: Fatorial
Fatorial de 4
9
Programação Recursiva
Uma função em C pode chamar ela mesma
Função recursiva
O código de uma função recursiva deve tratar o caso
base e o caso geral
Cada chamada da função cria novos parâmetros e
variáveis locais
Cria-se uma nova instância da função
Como em qualquer chamada de função, assim que a
função termina sua execução, o controle retorna para a
função que a chamou (que neste caso, é outra
instância da mesma função)
Exemplo de Função Recursiva:
Fatorial
int fatorial(int n) {
int resultado;
if (n == 0)
resultado = 1;
Caso Base
else
resultado = n * fatorial(n - 1);
return resultado;
}
Caso Geral
11
Chamando Função Recursiva: Fatorial
int main() {
int fat = fatorial(2);
printf(“Fatorial de 2 é %d”,fat);
return 0;
}
12
Pilha de Execução de Funções
Recursivas
1 – Chamada da função:
cópia do argumento
resultado
n
fat
2
-
resultado
n
resultado
n
<fatorial
fat
<main
4 – Retorno da 3a chamada:
cálculo da expressão
resultado
n
resultado
n
fat
1
1
2
-
2 – Chamada recursiva:
cópia do argumento
<fatorial’
<fatorial
<main
1
2
-
3 – Chamada recursiva:
cálculo da expressão
resultado
n
resultado
n
<fatorial’
resultado
n
<fatorial
fat
<main
5 – Retorno da 2a chamada:
cálculo da expressão
resultado
n
fat
2
2
-
<fatorial
<main
1
0
1
2
-
<fatorial’’
<fatorial’
<fatorial
<main
5 – Retorno da
1a chamada
fat
2
<main
13
Usando Recursividade para resolver
problemas
Problema: Torre de Hanoi
Deve-se transportar todos os discos da primeira estaca até
a última obedecendo as seguintes regras:
1. Só pode ser deslocado um disco por vez (o do topo de uma
estaca)
2. Em nenhum momento um disco maior pode estar sobre um
menor
14
Resolvendo Recursividade o Problema
da Torre de Hanoi
Solução: Torre de Hanoi
1. Mover n – 1 discos da estaca Origem para a Temporária
2. Mover o disco n da estaca Origem para a Destino
3. Mover n – 1 discos da estaca Temporária para a Destino
15
Torre de Hanoi
Caso Base
void mover(int n, char orig, char temp, char dest) {
if (n == 1)
printf("Mova o disco 1 da estaca %c para a estaca
%c\n",orig,dest);
else {
mover (n-1,orig,dest,temp);
printf("Mova o disco %d da estaca %c para a estaca
%c\n",n,orig,dest);
mover(n-1,temp,orig,dest);
}
}
Caso Geral
16
Algoritmo para a Torre de Hanoi com 4
Discos
Início
origem -> destino
17
Algoritmo para a Torre de Hanoi com 4
Discos
origem -> temp
destino -> temp
18
Algoritmo para a Torre de Hanoi com 4
Discos
origem -> destino
temp -> origem
19
Algoritmo para a Torre de Hanoi com 4
Discos
temp -> destino
origem -> destino
20
Pontos Chave de uma Solução
Recursiva
Definir o problema em termos recursivos
Definir o caso geral
Determinar o caso base
Definir uma solução de modo que a cada
chamada recursiva, podemos nos aproximar do
caso base
21
Recursão x Laço
Não é porque existe uma solução recursiva, que
sempre devemos usá-la
Soluções iterativas (com laço) são geralmente mais
eficientes
Soluções recursivas geralmente demandam mais poder de
processamento e memória
Porém, soluções utilizando recursão podem ser mais
elegantes e mais compreensíveis que soluções
iterativas equivalentes
Programador deve analisar caso a caso qual é a melhor
técnica a aplicar para a resolução do problema
22
Resumindo ...
Recursão
Conceito
Exemplos de definições recursivas
Casos Base e Geral
Programando Recursivamente
Recursão X Laço
23
Exercícios
O fatorial ímpar de um numero n ímpar positivo é o produto
de todos os numeros ímpares positivos menores do que ou
iguais a n. Por exemplo, 7! = 1 . 3 . 5 . 7 = 105.
Escreva
funcões
iterativas
e
recursivas
para
a
determinacao do fatorial impar de um inteiro impar dado.
24
Exercícios
/*Funcao iterativa para o calculo do fatorial impar*/
long int FatImpar(int n){
long int Fat;
int i;
if (n % 2 == 1) {
Fat = 1;
for (i = 3; i <= n; i = i + 2)
Fat = Fat * i;
return (Fat);
}
else
return(1);
}
25
Exercícios
/*Funcao recursiva para o calculo do fatorial impar*/
long int FatImparRec(int n) {
if (n % 2 == 1)
if (n == 1)
return(1);
else
return(n*FatImparRec(n-2));
else
return(-1);
}
26
Exercícios
Qual o valor de X (4)?
int X(int n) {
if (n == 1 || n == 2)
return n;
else
return X(n-1) + n * X(n-2);
}
27
Download

Recursividade