Post on 01-Jul-2015
Lógica de Programação
Recursividade
Regis Pires Magalhãesregis@cefetpi.br
Última atualização em 07/08/2008
Recursividade• Um algoritmo que para resolver um problema
divide-o em subprogramas mais simples, cujas soluções requerem a aplicação dele mesmo, é chamado recursivo, seja de forma direta ou indireta.
• Em geral, uma rotina recursiva R pode ser expressa como uma composição formada por um conjunto de comandos C (que não contém chamadas a R) e uma chamada (recursiva) à rotina R:
Recursão Direta
Exemplo• Fatorial
– A definição 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 verificável) dos fatoriais é que:– n! = n * (n-1)!
– Esta propriedade é chamada de propriedade recursiva: o fatorial de um numero pode ser calculado através 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
Caso base ou Condição de Parada
Como uma função recursiva pode chamar a si mesma indefinidamente, é essencial a existência do caso base, ou condição de parada.
Forma geral• Esquematicamente, os algoritmos recursivos têm 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 direção ao caso de base, senão o algoritmo não 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 F(4) = 4.6
Exemploalgoritmo "fatorial"varnumero: inteiro
funcao fat (n:Inteiro):Inteiroinicio se n=0 entao retorne 1 senao retorne n * Fat (n-1) fimsefimfuncao
inicio escreva("Digite um número: ") leia (numero) escreval("O fatorial de ", numero, " é ",
fat(numero))fimalgoritmo
Exemplo não recursivoalgoritmo "fatorial"varnumero: inteiro
funcao fat (n:Inteiro):Inteirovar i, resultado : inteiroinicio resultado <- 1 para i de n ate 1 passo -1 faca resultado <- resultado * i fimpara retorne resultadofimfuncao
inicio escreva("Digite um número: ") leia (numero) escreval("O fatorial de ", numero, " é ",
fat(numero))fimalgoritmo
Algoritmos Recursivos x Iterativos
• Todo algoritmo recursivo possui um algoritmo iterativo equivalente, mudando apenas a sua complexidade de construção.
• Vantagens– Simplifica a solução de alguns problemas
– Algoritmos recursivos são mais compactos para alguns tipos de algoritmo, mais legíveis e mais fáceis de ser compreendidos e implementados.
• Desvantagens– Por usarem intensivamente a pilha de execução, os algoritmos
recursivos tendem a ser mais lentos e a consumir mais memória que os iterativos, porém pode valer a pena sacrificar a eficiência em benefício da clareza.
– Erros de implementação podem levar a estouro de pilha. Isto é, caso não seja indicada uma condição de parada, ou se esta condição nunca for satisfeita, entre outros.
Recursão Indireta• Entretanto, pode-se ter também uma forma indireta
de recursão, na qual as rotinas são conectadas através de uma cadeia de chamadas recursivas que acaba retornando a primeira que foi chamada:
Torres de Hanói
• Quebra-cabeças com uma base de 3 pinos, onde num deles, são dispostos discos uns sobre os outros, em ordem crescente de diâmetro, 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 situação.
• O número de discos pode variar, sendo que o mais simples contém apenas três.
A Lenda
• "No grande templo de Benares, embaixo da cúpula que marca o centro do mundo, repousa uma placa de latão onde estão presas três agulhas de diamante, cada uma com 50 cm de altura e com espessura do corpo de uma abelha.
• Em uma dessas agulhas, durante a criação, Deus colocou sessenta e quatro discos de ouro puro, com o disco maior repousando sobre a placa de latão 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 imutáveis de Brahma, que exigem que o sacerdote em vigília não mova mais de um disco por vez e que ele coloque este disco em uma agulha de modo que não haja nenhum disco menor embaixo dele.
• Quando os sessenta e quatro discos tiverem sido assim transferidos da agulha em que a criação de Deus as colocou para uma das outras agulhas, a torre, o templo e os brâmanes virarão pó, e com um trovejar, o mundo desaparecerá."
Solução• 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).
Solução
Solução Ótima• O número mínimo de "movimentos" para
conseguir transferir todos os discos é 2n-1, sendo n o número de discos.
• Logo:– Para 3 discos , são necessários 7 movimentos– Para 7 discos, são necessários 127 movimentos– Para 15 discos, são necessários 32.767 movimentos– Para 64 discos, como diz a lenda, são necessários
18.446.744.073.709.551.615 movimentos.
Solução Recursiva• A solução para o problema da Torre de Hanoi com
recursividade é compacta e baseia-se no seguinte:– A única operação possível 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 solução 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 transferência da torre de cima não é uma operação possível de ser executada, ela deverá ser reduzida sucessivamente até transformar-se em um movimento de disco.
Solução Recursiva
Algoritmoalgoritmo "hanoi"var num_discos, numero_movimentos : inteiro
procedimento transfere(n : inteiro; origem, destino, auxiliar : caracter)iniciose (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)fimsefimprocedimento
inicioescreva("Digite o número de discos: ")leia(num_discos)transfere(num_discos, "A", "C", "B")escreval("Número total de movimentos: ", numero_movimentos)fimalgoritmo