Você está na página 1de 30

MC 102 – Algoritmos e Programação de Computadores

Recursão

• Definição: Um objeto é dito recursivo se for definido em termos


de si próprio.
Muito usada na matemática e na computação.

• Exemplo: Fatorial.

1 se n = 0.
n! :=
n(n − 1)! se n > 0.

• Esta idéia nos permite definir algoritmos que são recursivos, isto
é, algoritmos que são definidos em termos de si mesmos.
1
MC 102 – Algoritmos e Programação de Computadores

• Exemplo: Como implementar o fatorial usando recursão?


#include <stdio.h>
int fatorial(int);
int main( )
{
int n;
scanf(‘‘%d”,&n);
if (n >= 0)
printf(‘‘%s%d\n”, ‘‘Fatorial: ”, fatorial(n));
return 0;
}

2
MC 102 – Algoritmos e Programação de Computadores

• Exemplo: Como implementar o fatorial usando recursão?


#include <stdio.h>
int fatorial(int);
int main( )
{
int n;
scanf(‘‘%d”,&n);
if (n >= 0)
printf(‘‘%s%d\n”, ‘‘Fatorial: ”, fatorial(n));
return 0;
}

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

2
MC 102 – Algoritmos e Programação de Computadores

Observações importantes

• É vital que garantamos um número finito de chamadas


recursivas.
– Se isto não ocorrer entramos em um loop potencialmente
infinito.

3
MC 102 – Algoritmos e Programação de Computadores

Observações importantes

• É vital que garantamos um número finito de chamadas


recursivas.
– Se isto não ocorrer entramos em um loop potencialmente
infinito.

• Como garantir que a recursão seja finita?


– Uma chamada recursiva trabalha sobre uma instância.
– Para cada chamada recursiva deve ser passada uma instância
mais restrita que a da chamada anterior.
– Esta seqüência de restrições deve levar a uma instância
suficientemente simples que nos permita calcular o resultado
de maneira direta.

Esta(s) instância(s) suficientemente simples forma(m) a base da recursão


3
MC 102 – Algoritmos e Programação de Computadores

Exemplo: máximo de um vetor com n ≥ 1 elementos

#include <stdio.h>
#define MAX 100
int maximo( int v[ ], int n)
{
int i;
if ( n > 1) {
i = maximo(v, n-1);
if (v[n-1] > v[i])
i = n-1;
}
else i = 0;
return i;
}
4
MC 102 – Algoritmos e Programação de Computadores

Exemplo: máximo divisor comum

• gcd(4032, 1272) = 24
– 4032 = 26 × 32 × 71 ;
– 1272 = 23 × 31 × 531 ;
– gcd = 23 × 31 = 24.

5
MC 102 – Algoritmos e Programação de Computadores

Exemplo: máximo divisor comum

• gcd(4032, 1272) = 24
– 4032 = 26 × 32 × 71 ;
– 1272 = 23 × 31 × 531 ;
– gcd = 23 × 31 = 24.

• Propriedade: gcd(x, y) = gcd (y, x% y).

5
MC 102 – Algoritmos e Programação de Computadores

Exemplo: máximo divisor comum

• gcd(4032, 1272) = 24
– 4032 = 26 × 32 × 71 ;
– 1272 = 23 × 31 × 531 ;
– gcd = 23 × 31 = 24.

• Propriedade: gcd(x, y) = gcd (y, x% y).


– gcd(4032, 1272) = gcd(1272, 4032%1272) = gcd(1272, 216);

5
MC 102 – Algoritmos e Programação de Computadores

Exemplo: máximo divisor comum

• gcd(4032, 1272) = 24
– 4032 = 26 × 32 × 71 ;
– 1272 = 23 × 31 × 531 ;
– gcd = 23 × 31 = 24.

• Propriedade: gcd(x, y) = gcd (y, x% y).


– gcd(4032, 1272) = gcd(1272, 4032%1272) = gcd(1272, 216);
– gcd(1272, 216) = gcd(216, 1272%216) = gcd(216, 192);

5
MC 102 – Algoritmos e Programação de Computadores

Exemplo: máximo divisor comum

• gcd(4032, 1272) = 24
– 4032 = 26 × 32 × 71 ;
– 1272 = 23 × 31 × 531 ;
– gcd = 23 × 31 = 24.

• Propriedade: gcd(x, y) = gcd (y, x% y).


– gcd(4032, 1272) = gcd(1272, 4032%1272) = gcd(1272, 216);
– gcd(1272, 216) = gcd(216, 1272%216) = gcd(216, 192);
– gcd(216, 192) = gcd(192, 216%192) = gcd(192, 24);

5
MC 102 – Algoritmos e Programação de Computadores

Exemplo: máximo divisor comum

• gcd(4032, 1272) = 24
– 4032 = 26 × 32 × 71 ;
– 1272 = 23 × 31 × 531 ;
– gcd = 23 × 31 = 24.

• Propriedade: gcd(x, y) = gcd (y, x% y).


– gcd(4032, 1272) = gcd(1272, 4032%1272) = gcd(1272, 216);
– gcd(1272, 216) = gcd(216, 1272%216) = gcd(216, 192);
– gcd(216, 192) = gcd(192, 216%192) = gcd(192, 24);
– gcd(24, 192%24) = gcd(24, 0) = 24.

5
MC 102 – Algoritmos e Programação de Computadores

Exemplo: máximo divisor comum

• gcd(4032, 1272) = 24
– 4032 = 26 × 32 × 71 ;
– 1272 = 23 × 31 × 531 ;
– gcd = 23 × 31 = 24.

• Propriedade: gcd(x, y) = gcd (y, x% y).


– gcd(4032, 1272) = gcd(1272, 4032%1272) = gcd(1272, 216);
– gcd(1272, 216) = gcd(216, 1272%216) = gcd(216, 192);
– gcd(216, 192) = gcd(192, 216%192) = gcd(192, 24);
– gcd(24, 192%24) = gcd(24, 0) = 24.

x se y = 0.
gcd(x, y) :=
gcd(y, x%y) caso contrário.

5
MC 102 – Algoritmos e Programação de Computadores

Exemplo: máximo divisor comum


x se y = 0.
gcd(x, y) :=
gcd(y, x%y) caso contrário.

#include <stdio.h>

int gcd( int x, int y)


{
if (y == 0) return x
else return gcd(y, x%y);
}

6
MC 102 – Algoritmos e Programação de Computadores

Exemplo: números de Fibonacci


0 se n = 0.


Fn := 1 se n = 1.


Fn−1 + Fn−2 se n ≥ 2.

7
MC 102 – Algoritmos e Programação de Computadores

Exemplo: números de Fibonacci


0 se n = 0.


Fn := 1 se n = 1.


Fn−1 + Fn−2 se n ≥ 2.

Fib (n)
1. Se n ≤ 1 retorne n;
2. Senão retorne fib(n − 1) + fib(n − 2)

7
MC 102 – Algoritmos e Programação de Computadores

Fib (n)
1. Se n ≤ 1 retorne n;
2. Senão retorne fib(n − 1) + fib(n − 2)

• Calcular F3 produz a sequência de invocações de f ib(n) dada


abaixo (note a indentação). Qual é a sequência de invocações
para F5 ?

f ib(3)
f ib(2)
f ib(1)
f ib(0)
f ib(1)

• Faça uma versão iterativa de f ib(n).

8
MC 102 – Algoritmos e Programação de Computadores

O problema das torres de Hanoi

• Deseja-se mover os discos da torre A para a torre C, usando a


torre B como auxiliar, respeitando as seguintes regras:

1. Mover um disco por vez;


2. Nunca colocar um disco maior sobre um menor.

Torre A Torre B Torre C Torre A Torre B Torre C

9
MC 102 – Algoritmos e Programação de Computadores

Torres de Hanoi

Hanoi (n, inicio, fim, aux)


1. Se n = 1 imprima De “inicio” para “fim”
2. Senão
3. hanoi(n-1, inicio, aux, fim)
4. imprima De “inicio” para “fim”
5. hanoi(n-1, aux, fim, inicio)

10
MC 102 – Algoritmos e Programação de Computadores

Divisão e conquista

• Dividir o problema em um certo número de subproblemas;

• Conquistar os subproblemas resolvendo-os recursivamente. Se o


tamanho do subproblema é suficientemente pequeno resolva-o
diretamente;

• Combine as soluções do subproblema para encontrar uma


solução do problema original.

11
MC 102 – Algoritmos e Programação de Computadores

Exponenciação rápida

• Lembrem-se da idéia de fazer o cálculo de xk com economia de


multiplicações. Considerando qualquer k ≥ 0:

x k2 . x k2 , se k ≡ 0 (mod 2);
k
x =
x k−1 k−1
2 . x 2 . x, caso contrário.

• Vamos usar recursão para resolver o problema.

12
MC 102 – Algoritmos e Programação de Computadores

Exponenciação rápida

float FastExp(int n, float x) {


float aux = 1;

if (n > 0) {
aux = FastExp(n/2, x);
aux = aux * aux;
if (n % 2) aux = aux * x;
}

return aux;
}

13
MC 102 – Algoritmos e Programação de Computadores

MergeSort

• Divisão: divida o problema de ordenar uma sequência de n


números nos subproblemas de ordenar duas sequências de ⌊n/2⌋
e ⌈n/2⌉ elementos.

• Conquista: ordene as duas subsequências recursivamente.

• Combine: intercale as duas subsequências para obter a


sequência (original) ordenada.

14
MC 102 – Algoritmos e Programação de Computadores

Mergesort

mergesort (vet, inf, sup)


1. Se inf < sup então
2. meio ← ⌊ inf+sup
2 ⌋
3. mergesort( vet, inf, meio )
4. mergesort( vet, meio+1, sup )
5. merge( vet, inf, meio, sup )

15
MC 102 – Algoritmos e Programação de Computadores

Merge

void merge(int v[], int inf, int meio, int sup)


{
int i, j, k, vaux[MAX];
i = inf; j = meio+1; k = 0;
while (i <= meio && j <= sup) {
if (v[i] <= v[j]) vaux[k++] = v[i++];
else vaux[k++] = v[j++];
}
while (i <= meio) vaux[k++] = v[i++];
while (j <= sup) vaux[k++] = v[j++];
for (i = inf; i <= sup; i++) v[i] = vaux[i-inf];
return;
}
16
MC 102 – Algoritmos e Programação de Computadores

QuickSort

• Divisão: divida o problema de ordenar os elementos de um


vetor v[0, . . . , n − 1] no problema de ordenar dois subvetores
v[0, . . . , k] e v[k + 1, . . . , n − 1], onde todos os elementos do
primeiro subvetor são menores ou iguais aos elementos do
segundo subvetor.

• Conquista: ordene as duas subsequências recursivamente.

• Combine: nada mais precisa ser feito.

17
MC 102 – Algoritmos e Programação de Computadores

Quicksort

quicksort (vet, inf, sup)


1. Se inf < sup então
2. aux ← partition(vet, inf, sup)
3. quicksort( vet, inf, aux )
4. quicksort( vet, aux+1, sup )

18
MC 102 – Algoritmos e Programação de Computadores

Partition

int partition(int v[], int esq, int dir){


int i, j, aux, pivot;
i = esq-1; j = dir+1; pivot = v[esq];
do {
do i++; while (v[i] < pivot);
do j--; while (v[j] > pivot);
aux = v[i]; v[i] = v[j]; v[j] = aux;
} while (i < j);
if (j < i) {
aux = v[i]; v[i] = v[j]; v[j] = aux;
}
return j;
}
19
MC 102 – Algoritmos e Programação de Computadores

Recursão indireta

• Ocorre quando existem k rotinas, R1 , . . . , Rk , tais que


– a rotina Ri possui uma chamada à rotina Ri+1 , para i < k,
– e a rotina Rk possui uma chamada à rotina R1 ,
fechando o ciclo.

• Por exemplo: para k = 3 terı́amos:


– R1 chama R2 ;
– que chama R3 ;
– que chama R1 .

20
MC 102 – Algoritmos e Programação de Computadores

#include <stdio.h>
#include <math.h>
int impar(int);
int par(int);
int main (){
int n;
scanf(”%d”, &n);
n = abs(n);
if (impar(n)) printf(‘‘Ímpar!\n”);
else printf(‘‘Par!\n”);
return 0;
}
int impar(int n) {
if (n==0) return 0;
else return par(n-1);
}
int par(int n){
if (n==0) return 1;
else return impar(n-1);
}

21

Você também pode gostar