Você está na página 1de 17

Claudio Esperana

Python:
Python:
Recurso
Recurso
Recurso
Recurso

um princpio muito poderoso para construo de


algoritmos

A soluo de um problema dividido em

Casos simples:

So aqueles que podem ser resolvidos trivialmente

Casos gerais:

So aqueles que podem ser resolvidos compondo solues de


casos mais simples

Semelhante prova de teoremas por induo

Casos simples: O teorema verdadeiro trivialmente

Casos genricos: so provados assumindo-se que todos os


casos mais simples tambm so verdadeiros
Funo recursiva
Funo recursiva

Implementa um algoritmos recursivo onde a soluo dos casos


genricos requerem chamadas prpria funo

Uma funo recursiva a maneira mais direta (mas no


necessariamente a melhor) de se resolver problemas de natureza
recursiva ou para implementar estruturas de dados recursivas

Considere, por exemplo, a definio da seqncia de Fibonacci:

O primeiro e o segundo termo valem 0 e 1, respectivamente

O i-simo termo a soma do (i-1)-simo e o (i-2)-simo termo


>>> def fib(i):
if i==1: return 0
elif i==2: return 1
else: return fib(i-1)+fib(i-2)
>>> for i in range(1,11):
print fib(i),
0 1 1 2 3 5 8 13 21 34
Exemplo: Busca binria
Exemplo: Busca binria

Um exemplo clssico de recurso o algoritmo conhecido


como busca binria que usado para pesquisar um valor em
uma lista ordenada

Chamemos de iin e ia! os ndices mnimo e mximo da


lista onde a busca ser feita

Inicialmente, iin = 0 e ia! = len(lista)-1

O caso base corresponde a iin == ia!

Ento, ou o valor igual a lista [iin] ou no est na lista

Seno, podemos dividir o intervalo de busca em dois

Seja eio = (iin+ia!)"2

Se o valor maior que lista [eio] , ento ele se encontra em


algum dos ndices entre eio+1 e ia!

Caso contrrio, deve se encontrar em algum dos ndices


entre iin e eio
Busca binria: implementao
Busca binria: implementao
def testa(lista,#alor):
def bus$a%binaria(iin,ia!):
if iin==ia!: return iin
else:
eio=(ia!+iin)"2
if #alor>lista&eio':
return bus$a%binaria(eio+1,ia!)
else:
return bus$a%binaria(iin,eio)
i = bus$a%binaria(0,len(lista)-1)
if lista&i'==#alor:
print #alor,(en$ontrado na posi$ao(,i
else:
print #alor,(nao en$ontrado(
>>> testa(&1,2,5,),*,12',3)
3 nao en$ontrado
>>> testa(&1,2,5,),*,12',5)
5 en$ontrado na posi$ao 2
Recurso infinita
Recurso infinita

Assim como nos casos dos laos de repetio, preciso cuidado


para no escrever funes infinitamente recursivas

Ex.:
def re$ursi#a(!):
if f(!): return +rue
else: return re$ursi#a(!)

Uma funo recursiva tem que

Tratar todos os casos bsicos

Usar recurso apenas para tratar casos garantidamente mais


simples do que o caso corrente

Ex.:
def re$ursi#a(!):
if f(!): return +rue
elif !==0: return ,alse
else: return re$ursi#a(!-1)
Eficincia de funes recursivas
Eficincia de funes recursivas

Quando uma funo chamada, um pouco de memria


usado para guardar o ponto de retorno, os argumentos e
variveis locais

Assim, solues iterativas so normalmente mais


eficientes do que solues recursivas equivalentes

Isto no quer dizer que solues iterativas sempre sejam


preferveis a solues recursivas

Se o problema recursivo por natureza, uma soluo


recursiva mais clara, mais fcil de programar e,
freqentemente, mais eficiente
Pensando recursivamente
Pensando recursivamente

Ao invs de pensar construtivamente para para obter uma


soluo, s vezes mais simples pensar em termos de
uma prova indutiva

Considere o problema de testar se uma lista a uma


permutao da lista b

Caso bsico: a uma lista vazia

Ento a permutao de b se b tambm uma lista vazia

Caso bsico: a[0] no aparece em b

Ento a no uma permutao de b

Caso genrico: a[0] aparece em b na posio i

Ento a permutao de b se a[1:] uma permutao de b do


qual foi removido o elemento na posio i
Exemplo: !esta permutaes
Exemplo: !esta permutaes
def e%peruta$ao(a,b):
(((
-etorna +rue sse a lista a . ua
peruta/0o da lista b
(((
if len(a) == 0 : return len(b)==0
if a&0' in b:
i = b1inde!(a&0')
return e%peruta$ao(a&1:',b&0:i'+b&i+1:')
return ,alse
>>> e%peruta$ao(&1,2,3',&3,2,1')
+rue
>>> e%peruta$ao(&1,2,3',&3,3,1')
,alse
>>> e%peruta$ao(&1,2,3',&1,1,2,3')
,alse
>>> e%peruta$ao(&1,1,2,3',&1,2,3')
,alse
Estruturas de dados recursivas
Estruturas de dados recursivas

H estruturas de dados que so inerentemente recursivas, j


que sua prpria definio recursiva

Por exemplo, uma lista pode ser definida recursivamente:

[] uma lista (vazia)

Se A uma lista e x um valor, ento A+[x] uma lista com


x como seu ltimo elemento

Esta uma definio construtiva, que pode ser usada para


escrever funes que criam listas

Uma outra definio que pode ser usada para analisar listas :

Se L uma lista, ento:

L == [] , ou seja, L uma lista vazia, ou

x = L.pop() torna L uma lista sem seu ltimo elemento x

Esta definio no to til em Python j que o comando


for permite iterar facilmente sobre os elementos da lista
Exemplo: "ubse#$ncia
Exemplo: "ubse#$ncia
def e%subse2(a,b):
((( -etorna +rue sse a . subse234n$ia de b,
isto ., se todos os eleentos a&011n-1' de a
apare$e e b&5(0)', b&5(1)'111 b&5(n-1)'
onde 5(i)65(i+1) (((
if a == &':
7 8ista #a9ia . subse234n$ia de 22 lista
return +rue
if a&0' not in b:
return ,alse
return e%subse2 (a&1:', b&b1inde!(a&0')+1:')
Encontrando a recorrncia
Encontrando a recorrncia

Alguns problemas no se apresentam naturalmente como


recursivos, mas pensar recursivamente prov a soluo

Tome o problema de computar todas as permutaes de


uma lista

Assumamos que sabemos computar todas as permutaes


de uma lista sem seu primeiro elemento x

Seja perm uma dessas permutaes

Ento, a soluo do global contm todas as listas obtidas


inserindo x em todas as possveis posies de perm
Exemplo: computar todas as
Exemplo: computar todas as
permutaes de uma lista
permutaes de uma lista
def peruta$oes(lista):
((( :ada ua lista, retorna ua lista de listas,
onde $ada eleento . ua peruta/0o da lista
original (((
if len(lista) == 1: 7 ;aso base
return &lista'
prieiro = lista&0'
resto = lista &1:'
resultado = &'
for per in peruta$oes(resto):
for i in range(len(per)+1):
resultado += <
&per&:i'+&prieiro'+per&i:''
return resultado
!orres de %an&i
!orres de %an&i

Jogo que um exemplo clssico


de problema recursivo

Consiste de um tabuleiro com 3


pinos no qual so encaixados
discos de tamanho decrescente

A idia mover os discos de um


pino para outro sendo que:

S um disco movimentado
por vez

Um disco maior nunca pode


ser posto sobre um menor
!orres de %an&i: 'l(oritmo
!orres de %an&i: 'l(oritmo

A soluo simples se supusermos existir um algoritmo


capaz de mover todos os discos menos um do pino de
origem para o pino sobressalente

O algoritmo completo para mover n discos do pino de


origem A para o pino de destino B usando o pino
sobressalente C

Se n 1, ento a soluo trivial

Caso contrrio,

Usa-se o algoritmo para mover n-1 discos de A para C usando


B como sobressalente

Move-se o disco restante de A para B

Usa-se o algoritmo para mover n-1 discos de C para B usando


A como sobressalente
!orres de %an&i: )mplementao
!orres de %an&i: )mplementao
def =anoi(n,orige,destino,tep):
if n>1: =anoi(n-1,orige,tep,destino)
o#er(orige,destino)
if n>1: =anoi(n-1,tep,destino,orige)
def o#er(orige,destino):
print >?o#er de>, orige, >para@,<
>destino@

Com um pouco mais de trabalho, podemos redefinir a


funo mover para que ela nos d uma representao
grfica do movimento dos discos
!orres de %an&i: Exemplo
!orres de %an&i: Exemplo
A A A
B A A
BBB A A
BBBBB A A
=======================
A A A
A A A
BBB A A
BBBBB B A
=======================
A A A
A A A
A A A
BBBBB B BBB
=======================
A A A
A A A
A A B
BBBBB A BBB
=======================
A A A
A A A
A A B
A BBBBB BBB
=======================
A A A
A A A
A A A
B BBBBB BBB
=======================
A A A
A A A
A BBB A
B BBBBB A
=======================
A A A
A B A
A BBB A
A BBBBB A
=======================

Você também pode gostar