Módulo 7 - Percursos em grafos: largura, profundidade e caminho

Busca em profundidade: ir fundo primeiro

8 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 12/07/2026

O que você vai aprender

  • Entender a busca em profundidade como mergulhar fundo antes de voltar.
  • Reconhecer a pilha (ou a recursão) como a estrutura por trás da DFS.
  • Entender o backtrack: voltar ao bater num beco sem saída.
  • Comparar a ordem de visita da DFS com a da BFS.

Mergulhar antes de espalhar

Se a busca em largura é como as ondas de um lago, a busca em profundidade é como andar por um labirinto com uma regra teimosa: sempre siga em frente enquanto puder, e só quando bater numa parede volte um passo para tentar outra porta. Ela escolhe um vizinho, vai até ele, de lá escolhe outro vizinho, e continua descendo por esse fio único até não haver mais para onde ir. Nesse ponto ela recua até o último cruzamento onde ainda havia uma saída não testada e mergulha de novo. Em vez de cobrir tudo por perto antes de avançar, a DFS aposta em ir longe primeiro.

A estrutura que sustenta esse comportamento é a pilha, a estrutura LIFO em que o último a entrar é o primeiro a sair. Faz sentido: o vértice mais recente que você visitou é o que deve ser explorado em seguida, e é também o primeiro para onde você volta ao recuar. Na prática, muita gente escreve a DFS de forma recursiva, e aí a pilha nem aparece no código: quem guarda o caminho de volta é a pilha de chamadas de função, aquela mesma que você estudou nos módulos de pilha e recursão. Chamar a busca para um vizinho é descer; a chamada retornar é o backtrack acontecendo sozinho.

Um grafo em forma de árvore com A no topo, ligado a B e C. B liga a D e E. Uma seta grossa mostra o mergulho da busca em profundidade descendo A, B, D até o fundo, uma seta pontilhada de volta (backtrack) de D para B, depois descendo para E, e só então indo para C. Ao lado, uma pilha desenhada como caixas empilhadas mostra o caminho atual A, B, D de baixo para cima.
A busca em profundidade desce A, B, D até o fim, volta (backtrack) e tenta E, depois C. A pilha guarda o caminho de descida.

Pilha explícita ou recursão

Existem duas formas de escrever a busca em profundidade, e as duas fazem a mesma coisa. A versão recursiva é curta e lê quase como uma frase: visite este vértice, marque-o como visitado e, para cada vizinho ainda não visto, chame a busca nele. A recursão cuida do backtrack de graça, porque quando uma chamada termina o controle volta para a anterior. A versão com pilha explícita troca a recursão por uma pilha de verdade, empilhando os vizinhos e desempilhando o próximo a visitar. É útil quando o grafo é muito profundo e a recursão correria o risco de estourar a pilha de chamadas. As duas usam o mesmo conjunto de visitados da BFS, pelo mesmo motivo: não repetir e não entrar em loop.

função busca_profundidade(atual):
  adiciona atual em visitados
  escreva("visitando ", atual)
  para cada vizinho de atual faça
    se vizinho não está em visitados então
      busca_profundidade(vizinho)   // desce; o retorno é o backtrack
    fim
  fim

A versão recursiva da DFS. A pilha de chamadas guarda o caminho; quando a chamada retorna, a busca faz backtrack.

🎮 Jogo da aula

O mergulho da profundidade

A DFS parte de A e sempre desce pelo primeiro vizinho não visitado antes de voltar. Sabendo que A liga em B e C (nessa ordem), e que B liga em D, coloque os vértices na ordem em que a busca em profundidade os visita.

    Quando cada busca serve melhor

    As duas buscas visitam os mesmos vértices, mas em ordens bem diferentes, e cada uma brilha num tipo de problema. A busca em largura é a escolha quando você quer o caminho mais curto em passos, porque encontra cada vértice pela rota com menos arestas. A busca em profundidade é mais econômica de memória em grafos largos e é a base natural de qualquer coisa que envolva tentar um caminho e desistir dele: resolver um labirinto por tentativa e erro, descobrir se duas partes do grafo estão conectadas, encontrar todos os vértices de um mesmo bloco. Ela também é o esqueleto do backtracking, a técnica de tentar e voltar que aparece adiante no curso. Escolher entre largura e profundidade é escolher entre garantir o menor caminho e ir fundo com pouca memória.

    Teste rápido

    Na busca em profundidade escrita de forma recursiva, o que faz o papel da pilha que guarda o caminho de volta?

    Perguntas frequentes

    Qual a diferença essencial entre BFS e DFS?
    A ordem de exploração. A busca em largura espalha por camadas, visitando tudo que está perto antes de ir longe. A busca em profundidade mergulha num caminho até o fim antes de tentar outro. Uma usa fila, a outra usa pilha ou recursão. Visitam os mesmos vértices, mas em sequências diferentes, e cada uma serve melhor a certos problemas.
    Por que a DFS combina tão bem com recursão?
    Porque mergulhar num vizinho é, na prática, resolver o mesmo problema num pedaço menor do grafo, que é a essência da recursão. E a pilha de chamadas já guarda o caminho de volta sem esforço: quando uma chamada termina, o backtrack acontece sozinho. Por isso a versão recursiva costuma ser mais curta e clara que a com pilha explícita.
    A busca em profundidade acha o caminho mais curto?
    Não com garantia. Como ela mergulha antes de olhar os vizinhos próximos, o primeiro caminho que encontra até um destino pode ser bem mais longo que o ideal. Para o caminho mais curto em número de passos, a ferramenta certa é a busca em largura. A DFS serve para explorar, testar caminhos e cobrir todo o grafo.
    O que é estourar a pilha de chamadas?
    É quando a recursão desce fundo demais e a pilha de chamadas do programa fica sem espaço, causando um erro. Em grafos muito profundos, a DFS recursiva pode chegar nesse limite. A solução é usar a versão com pilha explícita, que guarda o caminho numa estrutura de dados sua, sem depender do limite da linguagem.
    A DFS também precisa do conjunto de visitados?
    Precisa, pelo mesmo motivo da BFS. Sem marcar quem já foi visto, um grafo com ciclo faria a busca voltar aos mesmos vértices para sempre. Na versão recursiva o esquecimento vira recursão infinita, que estoura a pilha. Marcar como visitado antes de descer para um vizinho é o que mantém a busca finita.
    Posso escrever a DFS sem recursão?
    Pode, e às vezes é preferível. A versão com pilha explícita coloca o vértice inicial numa pilha e, num laço, desempilha o topo, marca como visitado e empilha os vizinhos ainda não vistos. É a mesma lógica da recursão, só que com a pilha visível no código, o que evita o risco de estourar a pilha de chamadas em grafos profundos.

    Fontes

    Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.