Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Recursividade
Um algoritmo que para resolver um problema divide-o em subprogramas mais simples, cujas solues requerem a aplicao dele mesmo, chamado recursivo, seja de forma direta ou indireta. Em geral, uma rotina recursiva R pode ser expressa como uma composio formada por um conjunto de comandos C (que no contm chamadas a R) e uma chamada (recursiva) rotina R:
Recurso Direta
Exemplo
Fatorial
A definio de fatorial :
F(n) = 1 se n = 0 ou n = 1; F(n) = n * F(n-1), se n>1. onde n um numero inteiro positivo. Uma propriedade (facilmente verificvel) dos fatoriais que:
n! = n * (n-1)!
Esta propriedade chamada de propriedade recursiva: o fatorial de um numero pode ser calculado atravs do fatorial de seu antecessor.
F(4) = 4 * F(4-1) F(3) = 3 * F(3-1) F(2) = 2 * F(2-1) F(1) = 1 * F(1-1) F(0) = 1
Forma geral
Esquematicamente, os algoritmos recursivos tm a seguinte forma:
se "condicao para o caso de base" entao resolucao direta para o caso de base senao uma ou mais chamadas recursivas fimse
Caso Base
Um algoritmo recursivo pode ter um ou mais casos de base e um ou mais casos gerais. E para que o algoritmo termine, as chamadas recursivas devem convergir em direo ao caso de base, seno o algoritmo no terminar jamais. Convergir significa ter uma parte menor do problema para ser resolvido.
F(4) = 4.F(4-1) F(3) = 3.F(3-1) F(2) = 2.F(2-1) F(1) = 1.F(1-1) F(0) = 1 ------------ Caso Base F(1) = 1.1 F(2) = 2.1 F(3) = 3.2
Exemplo
algoritmo "fatorial" var numero: inteiro funcao fat (n:Inteiro):Inteiro inicio se n=0 entao retorne 1 senao retorne n * Fat (n-1) fimse fimfuncao inicio escreva("Digite um nmero: ") leia (numero) escreval("O fatorial de ", numero, " ", fat(numero)) fimalgoritmo
Exemplo no recursivo
algoritmo "fatorial" var numero: inteiro funcao fat (n:Inteiro):Inteiro var i, resultado : inteiro inicio resultado <- 1 para i de n ate 1 passo -1 faca resultado <- resultado * i fimpara retorne resultado fimfuncao inicio escreva("Digite um nmero: ") leia (numero) escreval("O fatorial de ", numero, " ", fat(numero)) fimalgoritmo
Desvantagens
Por usarem intensivamente a pilha de execuo, os algoritmos recursivos tendem a ser mais lentos e a consumir mais memria que os iterativos, porm pode valer a pena sacrificar a eficincia em benefcio da clareza. Erros de implementao podem levar a estouro de pilha. Isto , caso no seja indicada uma condio de parada, ou se esta condio nunca for satisfeita, entre outros.
Recurso Indireta
Entretanto, pode-se ter tambm uma forma indireta de recurso, na qual as rotinas so conectadas atravs de uma cadeia de chamadas recursivas que acaba retornando a primeira que foi chamada:
Torres de Hani
Quebra-cabeas com uma base de 3 pinos, onde num deles, so dispostos discos uns sobre os outros, em ordem crescente de dimetro, de cima para baixo. O problema consiste em passar todos os discos de um pino para outro qualquer, usando um dos pinos como auxiliar, de maneira que um disco maior nunca fique em cima de outro menor em nenhuma situao. O nmero de discos pode variar, sendo que o mais simples contm apenas trs.
A Lenda
"No grande templo de Benares, embaixo da cpula que marca o centro do mundo, repousa uma placa de lato onde esto presas trs agulhas de diamante, cada uma com 50 cm de altura e com espessura do corpo de uma abelha. Em uma dessas agulhas, durante a criao, Deus colocou sessenta e quatro discos de ouro puro, com o disco maior repousando sobre a placa de lato e os outros diminuindo cada vez mais ate o topo. Essa a torre de Brahma. Dia e noite, sem parar, os sacerdotes transferem os discos de uma agulha de diamante para outra de acordo com as leis ficas e imutveis de Brahma, que exigem que o sacerdote em viglia no mova mais de um disco por vez e que ele coloque este disco em uma agulha de modo que no haja nenhum disco menor embaixo dele. Quando os sessenta e quatro discos tiverem sido assim transferidos da agulha em que a criao de Deus as colocou para uma das outras agulhas, a torre, o templo e os brmanes viraro p, e com um trovejar, o mundo desaparecer."
Soluo
Algoritmo para mover N discos de A para C, usando B como auxiliar:
1. Se N==1, mova o nico disco de A para C e pare. 2. Se N>1:
1. Mova os N-1 discos superiores de A para B, usando C como auxiliar (passo 2 da figura abaixo). 2. Mova o disco restante de A para C (passo 3 da figura abaixo). 3. Mova os N-1 discos de B para C, usando A como auxiliar (passo 4 da figura abaixo).
Soluo
O nmero mnimo de "movimentos" para conseguir transferir todos os discos 2n-1, sendo n o nmero de discos. Logo:
Para 3 discos , so necessrios 7 movimentos Para 7 discos, so necessrios 127 movimentos Para 15 discos, so necessrios 32.767 movimentos Para 64 discos, como diz a lenda, so necessrios 18.446.744.073.709.551.615 movimentos.
Soluo tima
Soluo Recursiva
A soluo para o problema da Torre de Hanoi com recursividade compacta e baseia-se no seguinte:
A nica operao possvel de ser executada "move disco de um pino para outro"; Uma torre com (N) discos, em um pino, pode ser reduzido ao disco de baixo e a torre de cima com (N-1) discos; A soluo consiste em transferir a torre com (N-1) discos do pino origem para o pino auxiliar, mover o disco de baixo do pino origem para o pino destino e transferir a torre com (N-1) discos do pino auxiliar para o pino destino. Como a transferncia da torre de cima no uma operao possvel de ser executada, ela dever ser reduzida sucessivamente at transformar-se em um movimento de disco.
Soluo Recursiva
Algoritmo
algoritmo "hanoi" var num_discos, numero_movimentos : inteiro
procedimento transfere(n : inteiro; origem, destino, auxiliar : caracter) inicio se (n = 1) entao numero_movimentos <- numero_movimentos + 1 escreval(numero_movimentos, " - Mova de ", origem, " para ", destino) senao transfere(n-1, origem, auxiliar, destino) numero_movimentos <- numero_movimentos + 1 escreval(numero_movimentos, " - Mova de ", origem, " para ", destino) transfere(n-1, auxiliar, destino, origem) fimse fimprocedimento
inicio escreva("Digite o nmero de discos: ") leia(num_discos) transfere(num_discos, "A", "C", "B") escreval("Nmero total de movimentos: ", numero_movimentos) fimalgoritmo