Sie sind auf Seite 1von 8

Algoritmos Recursivos

Um objeto denominado recursivo quando sua definio parcialmente feita em termos dele mesmo. A recursividade (ou recurso) encontrada principalmente na matemtica, mas est presente em algumas situaes do cotidiano. Por exemplo, quando um objeto colocado entre dois espelhos planos paralelos e frente a frente surge uma imagem recursiva, porque a imagem do objeto refletida num espelho passa a ser o objeto a ser refletido no outro espelho e, assim, sucessivamente. Em programao, a recursividade um mecanismo til e poderoso que permite a uma funo chamar a si mesma direta ou indiretamente, ou seja, uma funo dita recursiva se ela contm pelo menos uma chamada explcita ou implcita a si prpria. A idia bsica de um algoritmo recursivo consiste em diminuir sucessivamente o problema em um problema menor ou mais simples, at que o tamanho ou a simplicidade do problema reduzido permita resolv-lo de forma direta, sem recorrer a si mesmo. Quando isso ocorre, diz que o algoritmo atingiu uma condio de parada, a qual deve estar presente em pelo menos um local dentro algoritmo. Sem esta condio o algoritmo no pra de chamar a si mesmo, at estourar a capacidade da pilha de execuo, o que geralmente causa efeitos colaterais e at mesmo o trmino indesejvel do programa. Para todo algoritmo recursivo existe um outro correspondente iterativo (no recursivo), que executa a mesma tarefa. Implementar um algoritmo recursivo (partindo de uma definio recursiva do problema) em uma linguagem de programao de alto nvel como Pascal e C simples e quase imediato, pois o seu cdigo praticamente transcrito para a sintaxe da linguagem. Por essa razo, em geral, os algoritmos recursivos possuem cdigo mais claro (legvel) e mais compacto do que os correspondentes iterativos. Alm disso, muitas vezes, evidente a natureza recursiva do problema a ser resolvido, como o caso de problemas envolvendo rvores estruturas de dados naturalmente recursivas. Entretanto, tambm h desvantagens: i) algoritmos recursivos quase sempre consomem mais recursos (especialmente memria, devido uso intensivo da pilha) do computador, logo tendem a apresentar um desempenho inferior aos iterativos; e ii) algoritmos recursivos so mais difceis de serem depurados, especialmente quando existem muitas chamadas em espera na pilha de execuo. Exemplo 1: Funo Fatorial (!) Esta funo um dos exemplos clssicos de recursividade e, por isso, de citao quase obrigatria. Eis sua definio recursiva:

se n = 0 1 n! = n (n 1)! se n > 0
Observe no Quadro 01 a facilidade em transformar a definio da funo para Portugol e C.

UFGD/FACET Prof. Wellington Lima dos Santos Algoritmos e Programao

Quadro 01 - Implementaes recursivas, em Portugol e C, da funo fatorial funo Fat(n : inteiro) : inteiro incio se n = 0 ento retorne 1 seno se n > 0 ento retorne n * Fat(n - 1) seno escreva(argumento invlido) fim pela definio, valor de 4! calculado como: 4!=4*3!=4*(3*2!)=4*(3*(2*1!))=4*(3*(2*(1*0!)))=4*(3*(2*(1*1)))=24 int Fat(int n) { if (n == 0) return 1; else if (n > 0) return n * Fat(n 1); else printf(argumento invlido) }

Note que funo chamada recursivamente com argumento decrescente at chegar ao caso trivial (0!), cujo valor 1. Este caso trivial (condio de parada) encerra a seqncia de chamadas recursivas. A seqncia de chamadas melhor ilustrada abaixo:

4! = 4 * 3! 3! = 3 * 2! 2! = 2 * 1! 1! = 1 * 0! 0! = 1 1! = 1 2! = 2 3! = 6 4! = 24 Como

O contexto de cada chamada empilhado Condio de parada O contexto de cada chamada desempilhado

n ! = n (n 1) (n 2)

3 2 1 , muito simples implementar um algoritmo iterativo da

funo fatorial. No Quadro 02, so apresentados dois algoritmos iterativos que se equivalem. H um pequeno detalhe que os diferencia da verso recursiva: no est sendo considerada a possibilidade de o argumento ser negativo, embora haja um comentrio sobre isso.

Quadro 02 - Implementaes iterativas, em Portugol e C, da funo fatorial funo Fat_NR(n : inteiro) : inteiro {vlido para n 0} declare i, x : inteiro incio x 1 para i 2 at n faa x x * i retorne x fim int Fat_NR(int n) /* vlido para n 0 */ { int i, x; x = 1; for (i = 2; i <= n; i++) x = x * i; return x; }

UFGD/FACET Prof. Wellington Lima dos Santos Algoritmos e Programao

Exemplo 2: Seqncia de Fibonacci A seqncia [0, 1, 1, 2, 3, 5, 8, 13, 21, ...] conhecida como seqncia ou srie de Fibonacci e tem aplicaes tericas (principalmente em teoria dos nmeros) e prticas, alguns padres na natureza parecem segui-la. Pode ser obtida atravs da definio recursiva:

n Fib(n) = Fib(n 1) + Fib(n 2)


a qual pode ser implementada como:

se 0 n 1 se n > 1

funo Fib(n : inteiro) : inteiro incio se n = 0 ou n = 1 ento retorne n seno se n > 1 ento retorne Fib(n-2) + Fib(n-1) seno {n < 0} escreva(Argumento invlido) fim Note que, para n > 1, cada chamada causa 2 novas chamadas de Fib, isto , o nmero total de chamadas cresce exponencialmente. Observe no diagrama de execuo abaixo que para Fib(5), so feitas 14 chamadas da funo. Alm disso, Fib(0) e Fib(1) so chamadas 3 vezes; Fib(1) chamada 5 vezes. Para Fib(25) so feitas 242784 chamadas recursivas!
F(5)

F(3)

F(4)

F(1)

F(2)

F(2)

F(3)

F(0)

F(1)

F(0)

F(1)

F(1) F(0)

F(2) F(1)

Figura 01 - Diagrama de execuo de Fib(5), para ilustrar que o nmero de chamadas cresce exponencialmente com o argumento de Fib. No caso da seqncia de Fibonacci relativamente simples implementar um algoritmo iterativo com complexidade O(n), que tire proveito dos valores j calculados. Eis uma possibilidade:

UFGD/FACET Prof. Wellington Lima dos Santos Algoritmos e Programao

funo Fib_NR(n : inteiro) : inteiro declare i, F1, F2, F : inteiro incio se n = 0 ou n = 1 ento retorne n seno se n > 1 ento incio F1 := 0 F2 := 1 para i 1 at n - 1 faa incio F F1 + F2 F1 F2 F2 F fim retorne F fim seno {n < 0} escreva(argumento invlido) fim Exemplo 2: Problema da Torre de Hani O problema ou quebra-cabea conhecido como torre de Hani foi publicado em 1883 pelo matemtico francs Edouard Lucas, tambm conhecido por seus estudos com a srie Fibonacci. Considerando que a torre A tenha n discos empilhados segundo dimetros decrescentes, o problema consiste em mover os n discos para torre C, com o mnimo de movimentos, usando a torre B como auxiliar. As duas regras so simples: somente o disco superior de uma das torres pode movido e um disco maior nunca pode ficar sobre outro menor.

6 5 4 3 2 1

Torre A
Figura 02 - Torres de Hani.

Torre B

Torre C

Soluo: Para entender melhor o problema, interessante analisarmos os casos sucessivamente mais complexos, comeando pelo mais simples: 1) A tem 1 disco movemos A[1]C[ ], isto , movemos o disco 1 de A para C. 2) A tem 2 discos movemos A[2]B[ ], A[1]C[ ] e B[2]C[1]. 3) A tem 3 discos movemos A[2,3]B[ ], A[1]C[ ] e B[2,3]C[1]. Mas pelas regras no podemos mover A[2,3] (sub-torre A composta pelos discos 2 e 3) diretamente para B[ ], nem B[2, 3]C[1]. Sem problemas! Vimos no 2 caso como mover uma torre com 2 discos de uma origem (A) para UFGD/FACET Prof. Wellington Lima dos Santos Algoritmos e Programao

uma torre destino (C), usando uma torre auxiliar (B). Para mover a sub-torre A[2,3] para B[ ], usamos a torre C como auxiliar. 4) A tem 4 discos movemos A[2,3,4]B[ ], A[1]C[ ], B[2,3,4]C[1]. Vimos no 3 caso como mover trs discos de uma origem para um destino.

n) A tem n discos movemos: A[2,3,4,...,n-1,n]B[ ], A[1]C[ ] e B[2,3,4,...,n-1,n]C[ ].

Para solucionarmos o problema com n discos, precisamos da soluo do problema com (n-1) discos, que requer a soluo do problema com (n-2) discos, e assim por diante, at chegarmos ao problema com 2 discos que depende da soluo trivial: mover apenas 1 disco de uma origem para um destino. A soluo para este problema um algoritmo surpreendentemente simples: procedimento MoveTorre(N : inteiro; Orig, Dest, Aux : caracter) incio se N = 1 ento Escreva(Movimento:, Orig, -> , Dest) seno incio MoveTorre(N - 1, Orig, Aux, Dest) Escreva(Movimento:, Orig, -> , Dest) MoveTorre(N - 1, Aux, Dest, Orig) fim fim

Para resolvermos o problema com 3 discos basta chamarmos MoveTorre(3, A, B, C) para obtermos a seguinte sada: Movimento: Movimento: Movimento: Movimento: Movimento: Movimento: Movimento: A A C A B B A -> -> -> -> -> -> -> C B B C A C C

B 1

B 2

B 3

B 4

B 5

B 6

B 7

Figura 03 - Seqncia de movimentos para solucionar o problema da Torre de Hani com 3 discos. Observe que o algoritmo MoveTorre faz duas a chamadas a si mesmo, portanto o nmero de movimentos cresce exponencialmente com o nmero de discos. Mais precisamente a soluo do problema com n discos requer 2n-1 movimentos. Assim, se uma pessoa se dispusesse a resolver o problema com 25 discos, com dedicao exclusiva de 8 horas por dia e realizando um movimento por UFGD/FACET Prof. Wellington Lima dos Santos Algoritmos e Programao

segundo, esta pobre criatura gastaria 3354431 segundos, ou seja, mais de 3 anos para solucionar o problema. O tempo dobra cada disco a mais! RESUMO Conceitos - Um algoritmo dito recursivo quando ele faz uma chamada a si mesmo, diretamente (podemos ver o algoritmo sendo chamado dentro dele mesmo) ou indireta (o algoritmo chama um outro algoritmo, que por sua vez invoca uma chamada ao primeiro). - Um algoritmo recursivo deve ter pelo menos uma condio de parada, para que no seja invocado indefinidamente. Esta condio de parada corresponde a instncias suficiente pequenas ou simples do problema original, que podem ser resolvidas diretamente. - Para todo algoritmo recursivo existe pelo menos um algoritmo iterativo correspondente e viceversa. Todavia, muitas vezes pode ser difcil encontrar essa correspondncia. Vantagens Os algoritmos recursivos normalmente so mais compactos, mais legveis e mais fceis de serem compreendidos. Algoritmos para resolver problemas de natureza recursiva so fceis de serem implementados em linguagens de programao de alto nvel. Desvantagens Por usarem intensivamente a pilha de execuo, o que requer alocaes e desalocaes de memria, os algoritmos recursivos tendem a ser mais lentos que os equivalentes iterativos, mas, em muitos casos, pode valer a pena sacrificar a eficincia em benefcio da clareza. Algoritmos recursivos so difceis de serem depurados durante a fase de desenvolvimento. Aplicaes - Nem sempre a natureza recursiva do problema garante que um algoritmo recursivo seja a melhor opo para resolv-lo. O algoritmo recursivo para obter a seqncia de Fibonacci um timo exemplo disso. - Algoritmos recursivos so aplicados em diversas situaes como em: i) problemas envolvendo manipulaes de rvores; ii) analisadores lxicos recursivos de compiladores; e ii) problemas que envolvem tentativa e erro ("Backtracking").

UFGD/FACET Prof. Wellington Lima dos Santos Algoritmos e Programao

Exerccios 1) Considere a funo Comb(n, k), que representa o nmero de grupos distintos com k pessoas que podem ser formados a partir de n pessoas. Por exemplo, Comb(4, 3) = 4, pois com 4 pessoas (A, B, C, D), possvel formar 4 diferentes grupos: ABC, ABD, ACD e BCD. Sabe-se que:

n Comb ( n, k ) = 1 Comb(n 1, k 1) + Comb( n 1, k )

se k = 1 se k = n se 1 < k < n

Implemente em portugol uma funo recursiva para Comb (n, k) e mostre o diagrama de execuo para chamada Comb (5, 3). Sabendo-se ainda Comb (n, k) = n! / (k! (n-k)!), implemente uma funo no recursiva de Comb (n, k). 2) Implemente recursivamente uma funo Max que retorne o maior valor armazenado em um vetor V, contendo n nmeros inteiros. 3) Dada a implementao em portugol da funo abaixo: funo F(N : inteiro) : inteiro incio se N < 4 ento F 3 N seno F 2 * F(N - 4) + 5 fim Quais so os valores de F(3) e de F(7)? 4) O clculo da raiz quadrada de um nmero real N pode ser feito atravs do seguinte algoritmo:

x RaizQ( N, x , ) = x2 + N RaizQ( N, ,) 2x

se | x 2 N | caso contrrio N e um erro admissvel. Implemente o

em que x uma aproximao inicial do valor

algoritmo em Portugol e mostre o diagrama de execuo para a chamada RaizQ(13, 3.2, 0.001). 5) Dada a definio da funo de Ackerman:

n + 1 A(m, n ) = A( n 1,1) A(m 1, A(m, n 1))

se m = 0 se m > 0 e n = 0 se m > 0 e n > 0

vlida para valores inteiros no negativos de m e n, implemente uma verso recursiva do algoritmo e faa o diagrama de execuo de A(1, 2). 6) A funo f(x, n) = xn, em que x um nmero real e n um nmero inteiro, pode ser calculada eficientemente como nos exemplos abaixo: x0 = 1; x1 = x; x2 = x2; x3 = x x2; x4 = (x2)2 x5 = x (x2)2; x6 = (x x2)2; x11 = x ((x (x2)2)2; x-2 = 1/x2 etc. Elabore a definio recursiva de f(x, n) e implemente um algoritmo recursivo para f(x,n).

UFGD/FACET Prof. Wellington Lima dos Santos Algoritmos e Programao

7) A recursividade pode ser utilizada para gerar todas as possveis permutaes de um conjunto de smbolos. Por exemplo, existem seis permutaes no conjunto de smbolos A, B e C: ABC, ACB, BAC, BCA, CBA e CAB. O conjunto de permutaes de N smbolos gerado tomando-se cada smbolo por vez e prefixando-o a todas as permutaes que resultam dos (N - 1) smbolos restantes. Conseqentemente, permutaes num conjunto de smbolos podem ser especificadas em termos de permutaes num conjunto menor de smbolos. Formule um algoritmo recursivo para este problema. 8) Considere uma partida de futebol entre duas equipes A x B, cujo placar final m x n, em que m e n so os nmeros de gols marcados por A e B, respectivamente. Implemente um algoritmo recursivo que imprima todas as possveis sucesses de gols marcados. Por exemplo, para um resultado de 3 x 1 as possveis sucesses de gols so "A A A B, "A A B A, "A B A A" e "B A A A".

UFGD/FACET Prof. Wellington Lima dos Santos Algoritmos e Programao

Das könnte Ihnen auch gefallen