SlideShare uma empresa Scribd logo
Python:
 Recursão



Claudio Esperança
Recursão
 É um princípio muito poderoso para construção de
  algoritmos
 A solução de um problema é dividido em
      Casos simples:
           São aqueles que podem ser resolvidos trivialmente
      Casos gerais:
           São aqueles que podem ser resolvidos compondo soluções de
            casos mais simples
 Semelhante à prova de teoremas por indução
    Casos simples: O teorema é verdadeiro trivialmente
    Casos genéricos: são provados assumindo-se que todos os
     casos mais simples também são verdadeiros
Função recursiva
 Implementa um algoritmos recursivo onde a solução dos casos
  genéricos requerem chamadas à própria função
 Uma função recursiva é a maneira mais direta (mas não
  necessariamente a melhor) de se resolver problemas de natureza
  recursiva ou para implementar estruturas de dados recursivas
 Considere, por exemplo, a definição da seqüência 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 binária
 Um exemplo clássico de recursão é o algoritmo conhecido
  como busca binária que é usado para pesquisar um valor em
  uma lista ordenada
 Chamemos de imin e imax os índices mínimo e máximo da
  lista onde a busca será feita
     Inicialmente, imin = 0 e imax =        len(lista)-1
 O caso base corresponde a imin == imax
     Então, ou o valor é igual a lista [imin] ou não está na lista
 Senão, podemos dividir o intervalo de busca em dois
     Seja meio = (imin+imax)/2
     Se o valor é maior que lista [meio] , então ele se encontra
      em algum dos índices entre meio+1 e imax
     Caso contrário, deve se encontrar em algum dos índices
      entre imin e meio
Busca binária: implementação
def testa(lista,valor):
    def busca_binaria(imin,imax):
        if imin==imax: return imin
        else:
            meio=(imax+imin)/2
            if valor>lista[meio]:
                return busca_binaria(meio+1,imax)
            else:
                return busca_binaria(imin,meio)
    i = busca_binaria(0,len(lista)-1)
    if lista[i]==valor:
        print valor,"encontrado na posicao",i
    else:
        print valor,"nao encontrado"

>>> testa([1,2,5,6,9,12],3)
3 nao encontrado
>>> testa([1,2,5,6,9,12],5)
5 encontrado na posicao 2
Recursão infinita
 Assim como nos casos dos laços de repetição, é preciso
  cuidado para não escrever funções infinitamente recursivas
    Ex.:
        def recursiva(x):
            if f(x): return True
            else: return recursiva(x)
 Uma função recursiva tem que
      Tratar todos os casos básicos
      Usar recursão apenas para tratar casos garantidamente
       mais simples do que o caso corrente
      Ex.:
        def recursiva(x):
            if f(x): return True
            elif x==0: return False
            else: return recursiva(x-1)
Eficiência de funções recursivas
 Quando uma função é chamada, um pouco de memória é
  usado para guardar o ponto de retorno, os argumentos e
  variáveis locais
 Assim, soluções iterativas são normalmente mais
  eficientes do que soluções recursivas equivalentes
 Isto não quer dizer que soluções iterativas sempre sejam
  preferíveis a soluções recursivas
 Se o problema é recursivo por natureza, uma solução
  recursiva é mais clara, mais fácil de programar e,
  freqüentemente, mais eficiente
Pensando recursivamente
 Ao invés de pensar construtivamente para para obter uma
  solução, às vezes é mais simples pensar em termos de
  uma prova indutiva
 Considere o problema de testar se uma lista a é uma
  permutação da lista b
      Caso básico: a é uma lista vazia
           Então a é permutação de b se b também é uma lista vazia
      Caso básico: a[0] não aparece em b
           Então a não é uma permutação de b
      Caso genérico: a[0] aparece em b na posição i
           Então a é permutação de b se a[1:] é uma permutação de b
            do qual foi removido o elemento na posição i
Exemplo: Testa permutações
def e_permutacao(a,b):
    """
    Retorna True sse a lista a é uma
    permutação da lista b
    """
    if len(a) == 0 : return len(b)==0
    if a[0] in b:
        i = b.index(a[0])
        return e_permutacao(a[1:],b[0:i]+b[i+1:])
    return False

>>> e_permutacao([1,2,3],[3,2,1])
True
>>> e_permutacao([1,2,3],[3,3,1])
False
>>> e_permutacao([1,2,3],[1,1,2,3])
False
>>> e_permutacao([1,1,2,3],[1,2,3])
False
Estruturas de dados recursivas
 Há estruturas de dados que são inerentemente recursivas, já
  que sua própria definição é recursiva
 Por exemplo, uma lista pode ser definida recursivamente:
    [] é uma lista (vazia)
    Se A é uma lista e x é um valor, então A+[x] é uma lista com
     x como seu último elemento
 Esta é uma definição construtiva, que pode ser usada para
  escrever funções que criam listas
 Uma outra definição que pode ser usada para analisar listas é:
    Se L é uma lista, então:
        L == [] , ou seja, L é uma lista vazia, ou

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

    Esta definição não é tão útil em Python já que o comando
     for permite iterar facilmente sobre os elementos da lista
Exemplo: Subseqüência
def e_subseq(a,b):
    """ Retorna True sse a é subseqüência de b,
    isto é, se todos os elementos a[0..n-1] de a
    aparecem em b[j(0)], b[j(1)]... b[j(n-1)]
    onde j(i)<j(i+1) """
    if a == []:
        # Lista vazia é subseqüência de qq lista
        return True
    if a[0] not in b:
        return False
    return e_subseq (a[1:], b[b.index(a[0])+1:])
Encontrando a recorrência
 Alguns problemas não se apresentam naturalmente como
  recursivos, mas pensar recursivamente provê a solução
 Tome o problema de computar todas as permutações de
  uma lista
      Assumamos que sabemos computar todas as permutações
       de uma lista sem seu primeiro elemento x
           Seja perm uma dessas permutações
           Então, a solução do global contém todas as listas obtidas
            inserindo x em todas as possíveis posições de perm
Exemplo: computar todas as
      permutações de uma lista
def permutacoes(lista):
    """ Dada uma lista, retorna uma lista de listas,
  onde cada elemento é uma permutação da lista
    original """
    if len(lista) == 1: # Caso base
        return [lista]
    primeiro = lista[0]
    resto = lista [1:]
    resultado = []
    for perm in permutacoes(resto):
        for i in range(len(perm)+1):
            resultado += 
               [perm[:i]+[primeiro]+perm[i:]]
    return resultado
Torres de Hanói
        Jogo que é um exemplo
         clássico de problema recursivo
        Consiste de um tabuleiro com 3
         pinos no qual são encaixados
         discos de tamanho decrescente
        A idéia é 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
Torres de Hanói: Algoritmo
 A solução é 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, então a solução é trivial
      Caso contrário,
           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
Torres de Hanói: Implementação
   def hanoi(n,origem,destino,temp):
       if n>1: hanoi(n-1,origem,temp,destino)
       mover(origem,destino)
       if n>1: hanoi(n-1,temp,destino,origem)

   def mover(origem,destino):
        print “Mover de“, origem, “para”,
        “destino”

 Com um pouco mais de trabalho, podemos redefinir a
  função mover para que ela nos dê uma representação
  “gráfica” do movimento dos discos
Torres de Hanói: Exemplo
   |       |       |         |       |       |
   *       |       |         |       |       |
  ***      |       |         |       |       *
 *****     |       |         |     *****    ***
=======================   =======================
   |       |       |         |       |       |
   |       |       |         |       |       |
  ***      |       |         |       |       |
 *****     *       |         *     *****    ***
=======================   =======================
   |       |       |         |       |       |
   |       |       |         |       |       |
   |       |       |         |      ***      |
 *****     *      ***        *     *****     |
=======================   =======================
   |       |       |         |       |       |
   |       |       |         |       *       |
   |       |       *         |      ***      |
 *****     |      ***        |     *****     |
=======================   =======================

Mais conteúdo relacionado

PPTX
Apresentação recursividade rev2
PPTX
Recursividade
PDF
Recursividade
PPT
Recursividade
PPTX
Estrutura de dados em Java - Recursividade
PPT
Logica Algoritmo 08 Recursividade
PDF
Haskell aula3 listas
ODP
Pymordida0 Semana de computação da SOCIESC - 2008/10
Apresentação recursividade rev2
Recursividade
Recursividade
Recursividade
Estrutura de dados em Java - Recursividade
Logica Algoritmo 08 Recursividade
Haskell aula3 listas
Pymordida0 Semana de computação da SOCIESC - 2008/10

Mais procurados (19)

PDF
Programação Dinâmica - Segmento de Soma Máxima
PDF
Python Funcional
PPT
Recursividade em C
PDF
Tutorial aed iii 007 - algoritmo de ordenação heapsort
PDF
Haskell aula2 tipos-e-classes
PDF
Análise de Algoritmos - Método Guloso
PDF
Tutorial aed iii 009 - algoritmo de ordenação heapsort
PPTX
PDF
Tutorial aed iii 008 - algoritmo de ordenação heapsort
PDF
Lista transforcacoes integrais
PDF
Algebra - Livro texto IV (UNIP/Matemática) 2018
PDF
Algoritmos e Programação: Manipulação de strings
PDF
Capítulo4 interpolação
PDF
Programando em python conjuntos
PDF
Vetores, Matrizes e Strings em C Parte 3
PDF
Análise de Algoritmos - Recursividade
PDF
Lista2
PDF
Equação de Recorrência - I (Otimização)
Programação Dinâmica - Segmento de Soma Máxima
Python Funcional
Recursividade em C
Tutorial aed iii 007 - algoritmo de ordenação heapsort
Haskell aula2 tipos-e-classes
Análise de Algoritmos - Método Guloso
Tutorial aed iii 009 - algoritmo de ordenação heapsort
Tutorial aed iii 008 - algoritmo de ordenação heapsort
Lista transforcacoes integrais
Algebra - Livro texto IV (UNIP/Matemática) 2018
Algoritmos e Programação: Manipulação de strings
Capítulo4 interpolação
Programando em python conjuntos
Vetores, Matrizes e Strings em C Parte 3
Análise de Algoritmos - Recursividade
Lista2
Equação de Recorrência - I (Otimização)
Anúncio

Semelhante a Programando em python recursao (20)

PPTX
Técnicas de Programação Funcional
PDF
15 algoritmos de busca em tabelas - sequencial e binaria
PDF
Listas Encadeadas
PDF
Pesquisa sequencial
PDF
Material_ Módulo 3_Python I.pptx.pdf - Python
PDF
Programação funcional tipada: uma introdução
PDF
Apostila rpira
PPT
Cálculo numérico
PDF
Usando numba onde python é lento
PPTX
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
PDF
Algebra - Livro texto III (UNIP/Matemática) 2018
PPTX
Equações Algébricas e Transcendentes - Isolamento de Raízes - @professorenan
PDF
Metódos de Pesquisa em C
PDF
Estrutura de dados
PDF
Apostila estrutura de dados 2
PDF
Paradigma Funcional - Caso de Estudo Haskell
KEY
Python 02
PDF
Calculo numerico capitulo 2
PDF
Python e django na prática
PDF
Heap - Python
Técnicas de Programação Funcional
15 algoritmos de busca em tabelas - sequencial e binaria
Listas Encadeadas
Pesquisa sequencial
Material_ Módulo 3_Python I.pptx.pdf - Python
Programação funcional tipada: uma introdução
Apostila rpira
Cálculo numérico
Usando numba onde python é lento
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
Algebra - Livro texto III (UNIP/Matemática) 2018
Equações Algébricas e Transcendentes - Isolamento de Raízes - @professorenan
Metódos de Pesquisa em C
Estrutura de dados
Apostila estrutura de dados 2
Paradigma Funcional - Caso de Estudo Haskell
Python 02
Calculo numerico capitulo 2
Python e django na prática
Heap - Python
Anúncio

Mais de samuelthiago (20)

PPTX
Eclipse i (1)
PPTX
Html básico
PPTX
Interface grafica em_java_parte_v
PPTX
Interface grafica em_java_parte_iv
PPTX
Interface grafica em_java_parte_iii
PPTX
Interface grafica em_java_parte_ii
PPTX
Interface grafica em_java_parte_i
PPTX
Poo interacao entre_objetos_blue_j_ii
PPTX
Introducao a poo_com_blue_j
PPT
Projeto calculadora em_java
PPT
Introducao a poo_com_blue_j
PDF
01 02 introdução aos bancos de dados (slides)
PDF
Java 08
PDF
Java 07
PDF
Java 06
PDF
Java 05
PDF
Java 04
PDF
Java 03
PDF
Java 02
PDF
Java 01
Eclipse i (1)
Html básico
Interface grafica em_java_parte_v
Interface grafica em_java_parte_iv
Interface grafica em_java_parte_iii
Interface grafica em_java_parte_ii
Interface grafica em_java_parte_i
Poo interacao entre_objetos_blue_j_ii
Introducao a poo_com_blue_j
Projeto calculadora em_java
Introducao a poo_com_blue_j
01 02 introdução aos bancos de dados (slides)
Java 08
Java 07
Java 06
Java 05
Java 04
Java 03
Java 02
Java 01

Programando em python recursao

  • 2. Recursão  É um princípio muito poderoso para construção de algoritmos  A solução de um problema é dividido em  Casos simples:  São aqueles que podem ser resolvidos trivialmente  Casos gerais:  São aqueles que podem ser resolvidos compondo soluções de casos mais simples  Semelhante à prova de teoremas por indução  Casos simples: O teorema é verdadeiro trivialmente  Casos genéricos: são provados assumindo-se que todos os casos mais simples também são verdadeiros
  • 3. Função recursiva  Implementa um algoritmos recursivo onde a solução dos casos genéricos requerem chamadas à própria função  Uma função recursiva é a maneira mais direta (mas não necessariamente a melhor) de se resolver problemas de natureza recursiva ou para implementar estruturas de dados recursivas  Considere, por exemplo, a definição da seqüência 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
  • 4. Exemplo: Busca binária  Um exemplo clássico de recursão é o algoritmo conhecido como busca binária que é usado para pesquisar um valor em uma lista ordenada  Chamemos de imin e imax os índices mínimo e máximo da lista onde a busca será feita  Inicialmente, imin = 0 e imax = len(lista)-1  O caso base corresponde a imin == imax  Então, ou o valor é igual a lista [imin] ou não está na lista  Senão, podemos dividir o intervalo de busca em dois  Seja meio = (imin+imax)/2  Se o valor é maior que lista [meio] , então ele se encontra em algum dos índices entre meio+1 e imax  Caso contrário, deve se encontrar em algum dos índices entre imin e meio
  • 5. Busca binária: implementação def testa(lista,valor): def busca_binaria(imin,imax): if imin==imax: return imin else: meio=(imax+imin)/2 if valor>lista[meio]: return busca_binaria(meio+1,imax) else: return busca_binaria(imin,meio) i = busca_binaria(0,len(lista)-1) if lista[i]==valor: print valor,"encontrado na posicao",i else: print valor,"nao encontrado" >>> testa([1,2,5,6,9,12],3) 3 nao encontrado >>> testa([1,2,5,6,9,12],5) 5 encontrado na posicao 2
  • 6. Recursão infinita  Assim como nos casos dos laços de repetição, é preciso cuidado para não escrever funções infinitamente recursivas  Ex.: def recursiva(x): if f(x): return True else: return recursiva(x)  Uma função recursiva tem que  Tratar todos os casos básicos  Usar recursão apenas para tratar casos garantidamente mais simples do que o caso corrente  Ex.: def recursiva(x): if f(x): return True elif x==0: return False else: return recursiva(x-1)
  • 7. Eficiência de funções recursivas  Quando uma função é chamada, um pouco de memória é usado para guardar o ponto de retorno, os argumentos e variáveis locais  Assim, soluções iterativas são normalmente mais eficientes do que soluções recursivas equivalentes  Isto não quer dizer que soluções iterativas sempre sejam preferíveis a soluções recursivas  Se o problema é recursivo por natureza, uma solução recursiva é mais clara, mais fácil de programar e, freqüentemente, mais eficiente
  • 8. Pensando recursivamente  Ao invés de pensar construtivamente para para obter uma solução, às vezes é mais simples pensar em termos de uma prova indutiva  Considere o problema de testar se uma lista a é uma permutação da lista b  Caso básico: a é uma lista vazia  Então a é permutação de b se b também é uma lista vazia  Caso básico: a[0] não aparece em b  Então a não é uma permutação de b  Caso genérico: a[0] aparece em b na posição i  Então a é permutação de b se a[1:] é uma permutação de b do qual foi removido o elemento na posição i
  • 9. Exemplo: Testa permutações def e_permutacao(a,b): """ Retorna True sse a lista a é uma permutação da lista b """ if len(a) == 0 : return len(b)==0 if a[0] in b: i = b.index(a[0]) return e_permutacao(a[1:],b[0:i]+b[i+1:]) return False >>> e_permutacao([1,2,3],[3,2,1]) True >>> e_permutacao([1,2,3],[3,3,1]) False >>> e_permutacao([1,2,3],[1,1,2,3]) False >>> e_permutacao([1,1,2,3],[1,2,3]) False
  • 10. Estruturas de dados recursivas  Há estruturas de dados que são inerentemente recursivas, já que sua própria definição é recursiva  Por exemplo, uma lista pode ser definida recursivamente:  [] é uma lista (vazia)  Se A é uma lista e x é um valor, então A+[x] é uma lista com x como seu último elemento  Esta é uma definição construtiva, que pode ser usada para escrever funções que criam listas  Uma outra definição que pode ser usada para analisar listas é:  Se L é uma lista, então:  L == [] , ou seja, L é uma lista vazia, ou  x = L.pop() torna L uma lista sem seu último elemento x  Esta definição não é tão útil em Python já que o comando for permite iterar facilmente sobre os elementos da lista
  • 11. Exemplo: Subseqüência def e_subseq(a,b): """ Retorna True sse a é subseqüência de b, isto é, se todos os elementos a[0..n-1] de a aparecem em b[j(0)], b[j(1)]... b[j(n-1)] onde j(i)<j(i+1) """ if a == []: # Lista vazia é subseqüência de qq lista return True if a[0] not in b: return False return e_subseq (a[1:], b[b.index(a[0])+1:])
  • 12. Encontrando a recorrência  Alguns problemas não se apresentam naturalmente como recursivos, mas pensar recursivamente provê a solução  Tome o problema de computar todas as permutações de uma lista  Assumamos que sabemos computar todas as permutações de uma lista sem seu primeiro elemento x  Seja perm uma dessas permutações  Então, a solução do global contém todas as listas obtidas inserindo x em todas as possíveis posições de perm
  • 13. Exemplo: computar todas as permutações de uma lista def permutacoes(lista): """ Dada uma lista, retorna uma lista de listas, onde cada elemento é uma permutação da lista original """ if len(lista) == 1: # Caso base return [lista] primeiro = lista[0] resto = lista [1:] resultado = [] for perm in permutacoes(resto): for i in range(len(perm)+1): resultado += [perm[:i]+[primeiro]+perm[i:]] return resultado
  • 14. Torres de Hanói  Jogo que é um exemplo clássico de problema recursivo  Consiste de um tabuleiro com 3 pinos no qual são encaixados discos de tamanho decrescente  A idéia é 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
  • 15. Torres de Hanói: Algoritmo  A solução é 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, então a solução é trivial  Caso contrário,  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
  • 16. Torres de Hanói: Implementação def hanoi(n,origem,destino,temp): if n>1: hanoi(n-1,origem,temp,destino) mover(origem,destino) if n>1: hanoi(n-1,temp,destino,origem) def mover(origem,destino): print “Mover de“, origem, “para”, “destino”  Com um pouco mais de trabalho, podemos redefinir a função mover para que ela nos dê uma representação “gráfica” do movimento dos discos
  • 17. Torres de Hanói: Exemplo | | | | | | * | | | | | *** | | | | * ***** | | | ***** *** ======================= ======================= | | | | | | | | | | | | *** | | | | | ***** * | * ***** *** ======================= ======================= | | | | | | | | | | | | | | | | *** | ***** * *** * ***** | ======================= ======================= | | | | | | | | | | * | | | * | *** | ***** | *** | ***** | ======================= =======================