Recursão aplicada a catálogos bibliotecários
Muita gente aprende recursão com listas encadeadas ou árvores binárias e acha que entendeu o conceito. Quando chega em um sistema real de biblioteca, a coisa muda de figura. A estrutura de dados natural para organizar acervo é uma floresta — ou seja, múltiplas árvores enraizadas — e isso é exatamente o que a recursão consegue modelar sem esforço. Vamos direto ao ponto. Em um sistema de gerenciamento de biblioteca uma função recursiva serve essencialmente para percorrer categorias hierárquicas, calcular resumos agregados ou localizar itens em subcategorias aninhadas. O exemplo mais clássico é um catálogo onde cada categoria pode ter subtítulos, e cada subtítulo pode ter outros subtítulos, e assim por diante. Não há limite fixo de profundidade imposto pela maioria dos sistemas.
Categoria recursiva em um sistema de gerenciamento de biblioteca uma função recursiva
Imagine a seguinte estrutura: • Ciências Exatas
• Ciências Humanas
– História
– História do Brasil
– Período Colonial
– Carta de Pero Vaz de Caminha
– Filosofia
Para listar todos os livros sob "Ciências Humanas", você não quer escrever um laço for dentro de outro laço for dentro de outro laço. Você escreve uma função que entra numa categoria, imprime ou processa os livros dela, e depois chama a si mesma para cada subcategoria. O código em Python fica algo assim:
def listar_livros(categoria): O problema de stack overflow aparece mais cedo do que a maioria espera. Há dois anos eu mantinha um sistema legado com cerca de oitenta mil registros organizados em cinquenta níveis de profundidade artificial. A recursão pura travava a thread em certas consultas de agregação. A solução que eu adotei foi transformar a função recursiva em uma versão iterativa usando uma pilha explícita (uma lista simples). O resultado foi o mesmo, mas sem depender da call stack do interpretador.
for livro in categoria.livros:
print(livro.titulo)
for sub in categoria.subcategorias:
listar_livros(sub)
Isso não significa que recursão sempre deva ser evitada. Significa que você precisa saber quando ela vai estourar. O limite padrão do Python é algo em torno de mil chamadas aninhadas, mas em sistemas embarcados ou em Linguagens como Java em servidores com threads pequenas, esse número pode ser bem menor.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Outros usos práticos da recursão nessa área
Além de listar categorias, a recursão é útil para: • Calcular o total de exemplares em uma ramificação completa (soma recursiva)
• Encontrar a categoria mais profunda de um acervo
• Gerar a árvore completa de dependências de classificação (ex: Dewey ou LCC)
• Verificar se um livro pertence a alguma subcategoria de um grupo maior
A soma recursiva é particularmente simples e comum: def total_exemplares(categoria):
total = len(categoria.livros)
for sub in categoria.subcategorias:
total += total_exemplares(sub)
return total
Um detalhe que pouca gente comenta: funções recursivas em Python não fazem otimização de (tail call optimization). Isso significa que cada chamada adicional consome memória de stack de verdade. Se você precisa de performance em um sistema com milhares de categorias, considere usar memoização ou iterar explicitamente.
Pegadinhas comuns
Um erro frequente é esquecer o caso base. Sem ele, a função entra em loop infinito e consome toda a memória disponível até o sistema derrubar o processo. Outro erro é confundir recursão com iteração aninhada genérica: às vezes um simple BFS (busca em largura) com uma fila é mais legível e menos arriscado do que uma recursão profunda. Se o seu sistema já está rodando em produção, faça um teste de carga com uma árvore de categorias sintética antes de liberar a versão recursiva. Eu vi colegas perderem meia noite de operação por causa de uma consulta recursiva mal delimitada que entrou em loop em um nó mal estruturado.
Aqui está uma versão mais segura, com proteção contra ciclos e limite de profundidade: def listar_livros_seguro(categoria, profundidade_max=20, visitados=None):
if visitados is None:
visitados = set()
id_cat = id(categoria)
if id_cat in visitados or profundidade_max <= 0:
return
visitados.add(id_cat)
for livro in categoria.livros:
print(livro.titulo)
for sub in categoria.subcategorias:
listar_livros_seguro(sub, profundidade_max - 1, visitados)
Isso previne tanto loops infinitos quanto estouro de stack, desde que você defina um limite razoável. Para a maioria dos acervos reais, vinte níveis já é mais do que suficiente.