Algoritmos

Recursividade: o que é e como funciona (com exemplos)

Capa do artigo Recursividade: o que é e como funciona (com exemplos)
Leitura com foco

Entenda o contexto.
Leve para a prática.

Neste artigo
  1. Como funciona a recursividade?
  2. O que é o fatorial?
  3. Para que serve o fatorial na prática?
  4. Exemplo de recursividade: o fatorial
  5. O que acontece por dentro de uma função recursiva?
  6. O que acontece se eu esquecer o caso base?
  7. Agora é com você!
  8. Recursividade ou laço de repetição?

Recursividade é quando uma função chama a si mesma para resolver um problema, dividindo-o em versões cada vez menores dele mesmo, até chegar a um caso tão simples que a resposta é imediata. Esse caso simples se chama caso base.

No artigo sobre funções, você viu que uma função pode ser chamada quantas vezes você quiser. A pergunta de hoje é: e se ela chamar ela mesma? Parece coisa de maluco, eu sei kkkk. Mas calma! No final das contas vai ser tudo bem simples.

Como funciona a recursividade?

Pense nas bonecas russas, aquelas que têm uma boneca menor dentro da outra. Para chegar na última, você abre uma, encontra outra igual, só que menor, abre de novo… até chegar na boneca que não abre mais. Essa última é o caso base. Depois você fecha todas, uma por uma, voltando pelo mesmo caminho.

Quatro bonecas russas em fila, da maior para a menor, com setas de abrir na ida e de fechar na volta; a menor, que não abre, é o caso base
Abrir uma boneca é como fazer mais uma chamada. A que não abre é o caso base, e fechar todas é o caminho de volta.

Toda função recursiva tem duas partes, e você precisa das DUAS:

  • Caso base: a condição que diz quando parar.
  • Chamada recursiva: a função chama a si mesma, sempre com um problema menor que o anterior.

O que é o fatorial?

Antes do código, vale conhecer o personagem do nosso exemplo. O fatorial vem da matemática: é o produto de um número natural por todos os que vêm antes dele, até chegar no 1. O símbolo é o ponto de exclamação, colocado depois do número. Assim:

  • 3! = 3 × 2 × 1 = 6
  • 4! = 4 × 3 × 2 × 1 = 24
  • 5! = 5 × 4 × 3 × 2 × 1 = 120

Não, a matemática não está gritando com você. O 5! é só o jeito curto de escrever a multiplicação inteira.

Um detalhe: por definição, 0! = 1. E repare como o fatorial cresce rápido: 10! já é 3.628.800, e 20! é 2.432.902.008.176.640.000.

Para que serve o fatorial na prática?

Para contar possibilidades. Veja três usos:

  • Ordenar coisas (permutações): n itens diferentes podem ser colocados em fila de n! formas. Três livros, A, B e C, cabem na prateleira em 3! = 6 ordens: ABC, ACB, BAC, BCA, CAB e CBA. Seis pessoas em uma fila: 6! = 720 ordens.
  • Formar anagramas: as 5 letras da palavra MARTE podem ser embaralhadas de 5! = 120 formas.
  • Escolher grupos (combinações): quando a ordem não importa, a conta é n! ÷ (k! × (n − k)!), em que k é o tamanho do grupo. Escolher 4 funcionários entre 10 dá 210 grupos. Escolher 6 números entre 60 dá 50.063.860 combinações.

Essas contagens são o primeiro passo no cálculo de probabilidades: para saber a chance de um resultado, é preciso contar quantos resultados existem.

Na programação, o fatorial aparece quando um programa precisa testar todas as ordens possíveis de alguma coisa. Com 10 itens, são 3.628.800 ordens. Com 20, o número já tem 19 dígitos. “Testar tudo” deixa de ser opção bem depressa.

O Python já traz essa conta pronta: math.factorial(5) devolve 120. Mas hoje nós vamos escrever a nossa, porque o fatorial tem uma característica que interessa muito a este artigo.

Exemplo de recursividade: o fatorial

O fatorial é o exemplo clássico de recursividade, e agora você vai ver o motivo. Olhe com atenção para a conta: 5! = 5 × 4 × 3 × 2 × 1. O trecho 4 × 3 × 2 × 1 é o 4!. Ou seja, 5! = 5 × 4!. Do mesmo jeito, 4! = 4 × 3!, e assim por diante… O problema contém uma versão menor dele mesmo! É a boneca dentro da boneca. O caso base é o 1!, que vale 1 e não precisa de conta nenhuma. Veja em PHP:

<?php

function fatorial(int $n): int
{
    if ($n <= 1) {
        return 1; // caso base: aqui a função para de se chamar
    }

    return $n * fatorial($n - 1); // chamada recursiva
}

echo fatorial(5), PHP_EOL; // 120

Em Python:

def fatorial(n):
    if n <= 1:
        return 1  # caso base: aqui a função para de se chamar

    return n * fatorial(n - 1)  # chamada recursiva


print(fatorial(5))  # 120

E em C:

#include <stdio.h>

int fatorial(int n) {
    if (n <= 1) {
        return 1; // caso base: aqui a função para de se chamar
    }

    return n * fatorial(n - 1); // chamada recursiva
}

int main(void) {
    printf("%d\n", fatorial(5)); // 120
    return 0;
}

ATENÇÃO: lembra que o fatorial cresce rápido? Isso aparece no código. Testei aqui: na versão em C, com o tipo int de 4 bytes, a conta sai certa até 12! (479.001.600). O 13! é 6.227.020.800, não cabe mais na variável, e fatorial(13) mostrou um número errado: 1932053504. Na versão em PHP, fatorial(20) funcionou, e fatorial(21) parou com TypeError: fatorial(): Return value must be of type int, float returned. No Python, fatorial(21) devolveu 51090942171709440000, sem erro.

O que acontece por dentro de uma função recursiva?

Veja o passo a passo de fatorial(4):

PassoChamadaO que ela faz
1fatorial(4)Espera o resultado de fatorial(3)
2fatorial(3)Espera o resultado de fatorial(2)
3fatorial(2)Espera o resultado de fatorial(1)
4fatorial(1)Caso base: devolve 1
5fatorial(2)Devolve 2 × 1 = 2
6fatorial(3)Devolve 3 × 2 = 6
7fatorial(4)Devolve 4 × 6 = 24
As chamadas descem até o caso base e depois são resolvidas de trás para frente.

Percebe que as chamadas vão se empilhando e depois são resolvidas na ordem inversa? O computador guarda cada chamada em uma pilha: a última que entrou é a primeira que sai.

Diagrama das chamadas de fatorial(4) se empilhando até o caso base e sendo resolvidas na volta
As chamadas de fatorial(4): primeiro elas se empilham, depois são resolvidas de trás para frente.
Ver a animação da pilha de chamadas de fatorial(4)
Animação da pilha de chamadas de fatorial(4): as chamadas se empilham até o caso base e depois são resolvidas de cima para baixo, até o resultado 24
O mesmo passo a passo em movimento: as chamadas sobem até o caso base, e as respostas descem até o resultado.

O que acontece se eu esquecer o caso base?

A função nunca para de se chamar, a pilha enche e o programa quebra. Veja esta função em Python, sem caso base:

def contagem(n):
    print(n)
    contagem(n - 1)  # sem caso base: nunca para


contagem(3)

Testei aqui e o programa terminou com o erro RecursionError: maximum recursion depth exceeded. No PHP, o manual oficial avisa que recursão infinita é considerada erro de programação, e que chamadas recursivas acima de 100 a 200 níveis já podem esgotar a pilha e encerrar o script.

Agora é com você!

Escreva uma função recursiva que soma todos os números de 1 até n. Para n = 4, o resultado é 10 (4 + 3 + 2 + 1). Antes de digitar, responda no papel: qual é o caso base? E qual é a chamada recursiva?

Se você respondeu essas duas perguntas, o código já está pronto na sua cabeça!!! Tente sozinho antes de pedir a resposta para alguém. É usando o seu raciocínio que você aprende de verdade.

Recursividade ou laço de repetição?

Tudo que você faz com recursividade dá para fazer com um laço de repetição, e vice-versa. Então quando usar cada um?

RecursividadeLaço de repetição
Combina comProblemas que se dividem em partes iguais e menores, como pastas dentro de pastasRepetições simples, com começo e fim conhecidos
MemóriaUsa a pilha a cada chamadaUsa menos memória
LeituraCostuma ficar mais curtaMais direta para quem está começando
Diferença entre recursividade e laço de repetição.

Para o fatorial, sendo bem sincero, o laço resolve melhor. Usei esse exemplo porque é o mais fácil de enxergar. A recursividade brilha mesmo quando chegarmos em árvores e nos algoritmos de busca e ordenação.

E é para lá que vamos! No próximo artigo você vai conhecer a busca binária, um jeito muito rápido de achar um valor dentro de um vetor. Até lá!

Confiança Sempre!!!

Fontes:

Sobre quem escreve

Walmir Silva

Olá! Sou Walmir, engenheiro de software com MBA em Engenharia de Software e o cérebro por trás do GrowthCode e autor do livro "Além do Código".

Se você acha que programação é apenas sobre escrever código, prepare-se para expandir seus horizontes. Aqui, nós vamos além do código e exploramos as interseções fascinantes entre tecnologia, negócios, artes e filosofia.

Você está em busca de crescimento na carreira? Quer se destacar em um mercado competitivo? Almeja uma vida mais rica em conhecimento e realização? Então você chegou ao lugar certo. No GrowthCode, oferecemos insights profundos, estratégias comprovadas e um toque de sabedoria filosófica para catalisar seu crescimento pessoal e profissional.

Ver todos os artigos →

Continue a conversa

Compartilhe sua perspectiva

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Encontre sua próxima resposta

O que você quer aprender?

Preferências de cookies

Os cookies opcionais começam desligados. Você pode mudar a escolha a qualquer momento por esta tela.

NecessáriosSempre ativos

Guardam a sua escolha de cookies e mantêm o site funcionando. Não são usados para publicidade.

Contam visitas e mostram como o site é usado: Google Analytics e Microsoft Clarity, carregados pelo Google Tag Manager. Como esse contêiner também carrega tags de publicidade, as estatísticas só são ativadas junto com Publicidade e marketing.

Exibem anúncios do Google AdSense e medem campanhas e e-mails: pixels da Meta e do TikTok e o Mautic.

Permite que o Google escolha anúncios com base nos seus interesses. Desligado, os anúncios aparecem sem personalização. Depende de Publicidade e marketing.

Também é possível bloquear cookies nas configurações do navegador. Detalhes na Política de privacidade.