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.
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):
Passo
Chamada
O que ela faz
1
fatorial(4)
Espera o resultado de fatorial(3)
2
fatorial(3)
Espera o resultado de fatorial(2)
3
fatorial(2)
Espera o resultado de fatorial(1)
4
fatorial(1)
Caso base: devolve 1
5
fatorial(2)
Devolve 2 × 1 = 2
6
fatorial(3)
Devolve 3 × 2 = 6
7
fatorial(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.
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)
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?
Recursividade
Laço de repetição
Combina com
Problemas que se dividem em partes iguais e menores, como pastas dentro de pastas
Repetições simples, com começo e fim conhecidos
Memória
Usa a pilha a cada chamada
Usa menos memória
Leitura
Costuma ficar mais curta
Mais 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á!
IFSC, Câmpus Tubarão. Análise Combinatória, com o símbolo do fatorial e os exemplos da fila de 6 pessoas, dos anagramas de MARTE e do sorteio de 4 entre 10.
Documentação do Python. Módulo math (em inglês), com a função factorial.
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.
Usamos cookies necessários para o site funcionar. Com a sua permissão, também usamos cookies de estatística e de publicidade e marketing. Você pode mudar a escolha quando quiser em Preferências de cookies. Política de privacidade
Continue a conversa