Menu
Coddy logo textTech

Busca em profundidade (DFS)

Última atualização

A busca em profundidade explora um grafo indo o mais fundo possível por cada ramo antes de retroceder. Começando por um nó de origem, ela visita um vizinho, depois o vizinho desse vizinho, e assim por diante até chegar a um beco sem saída (um nó sem vizinhos não visitados), momento em que retrocede e tenta o próximo ramo. Pressione reproduzir acima para vê-la descer por um caminho, atingir o fundo e sair.

A DFS é expressa naturalmente com uma pilha: seja uma pilha explícita (como animada aqui) ou a pilha de chamadas via recursão. Ela visita cada nó e aresta uma vez, portanto executa em tempo O(V + E) para um grafo com V vértices e E arestas.

Complexidade de tempo e espaço

MedidaComplexidadeNotas
TempoO(V + E)Cada vértice e aresta é visitado uma vez
EspaçoO(V)Pilha + conjunto de visitados, no pior caso todos os nós
TravessiaMais profundo primeiroSegue um ramo até o fim antes dos outros
Estrutura de dadosPilha (ou recursão)A ordem LIFO impulsiona o comportamento em profundidade

Passo a passo

PassoO que acontece
1Empilhe o nó de origem na pilha.
2Desempilhe um nó; se já foi visitado, ignore-o.
3Marque-o como visitado e registre a aresta que o alcançou.
4Empilhe todos os seus vizinhos não visitados.
5Repita até que a pilha esteja vazia.

Exemplo resolvido

DFS iterativa a partir de A no grafo A → [B, C], B → [D], C → [E], empilhando os vizinhos na ordem indicada (a pilha LIFO desempilha primeiro o último empilhado):

PassoPilha (topo à direita)VisitadosAção
1[A]{}Empilha a origem A.
2[B, C]{A}Desempilha A, marca visitado, empilha os vizinhos B e depois C.
3[B, E]{A, C}Desempilha C, marca visitado, empilha o vizinho E.
4[B]{A, C, E}Desempilha E, marca visitado, sem vizinhos.
5[D]{A, C, E, B}Desempilha B, marca visitado, empilha o vizinho D.
6[]{A, C, E, B, D}Desempilha D, marca visitado, pilha vazia: concluído.

Quando usar DFS

Use quandoEvite quando
Você precisa de detecção de ciclos, ordenação topológica ou encontrar componentes conexas.Você precisa do caminho mais curto em um grafo não ponderado: isso é feito pela BFS, não pela DFS.
O grafo é largo e raso, então uma pilha usa muito menos memória que uma fila com muitos nós de fronteira.O grafo é muito profundo e você usa recursão: a pilha de chamadas pode estourar.
Você quer explorar caminhos de forma exaustiva, como na resolução de labirintos ou na busca com backtracking.Você precisa descobrir os nós na ordem de distância a partir da origem.
Você verifica alcançabilidade ou se existe um caminho entre dois nós.Você deve garantir o número mínimo de arestas no caminho encontrado.

Uma implementação limpa e executável de Depth-First Search em Python, JavaScript, Java, C++, C. Escolha uma linguagem, copie o código ou abra-o já carregado no Playground da Coddy.

Código de Depth-First Search em Python

Python
1def dfs(graph, node, visited):2    visited.add(node)3    order = [node]4    for neighbor in graph[node]:5        if neighbor not in visited:6            order.extend(dfs(graph, neighbor, visited))7    return order8
9
10graph = {11    "A": ["B", "C"],12    "B": ["D", "E"],13    "C": ["F"],14    "D": [],15    "E": ["F"],16    "F": [],17}18
19order = dfs(graph, "A", set())20print("DFS order:", " -> ".join(order))
Execute este código no Playground de Python

Perguntas frequentes sobre a busca em profundidade

Qual é a complexidade de tempo da DFS?
A DFS executa em tempo O(V + E), onde V é o número de vértices e E o de arestas, porque visita cada vértice uma vez e examina cada aresta uma vez. Usa espaço O(V) para a pilha e o conjunto de visitados.
Qual é a diferença entre DFS e BFS?
A DFS usa uma pilha e mergulha fundo por um ramo antes de retroceder, enquanto a BFS usa uma fila e explora nível por nível, primeiro os nós mais próximos. A BFS encontra o caminho mais curto em um grafo não ponderado; a DFS não, mas usa menos memória em grafos largos e é natural para tarefas como detecção de ciclos e ordenação topológica.
A DFS é recursiva ou iterativa?
Ambas funcionam. A versão recursiva usa implicitamente a pilha de chamadas do programa e é muito concisa; a versão iterativa usa uma pilha explícita (como a animação aqui) e evita estouros de pilha por recursão profunda em grafos grandes.
Quando devo usar DFS em vez de BFS?
Use DFS quando precisar explorar caminhos inteiros: detecção de ciclos, ordenação topológica, componentes conexas ou busca com backtracking como resolver um labirinto. Ela também usa menos memória em grafos largos, já que a pilha só contém a fronteira de um ramo por vez. Recorra à BFS quando precisar do caminho mais curto em um grafo não ponderado ou dos nós em ordem de distância a partir da origem.
A DFS consegue encontrar o caminho mais curto?
Não de forma confiável. A DFS retorna o primeiro caminho que encontra, que muitas vezes não é o de menos arestas, porque ela se compromete a mergulhar fundo em vez de se expandir uniformemente. Para caminhos mais curtos em um grafo não ponderado use BFS, e para grafos ponderados use o algoritmo de Dijkstra.
Por que a DFS precisa de um conjunto de visitados?
Sem um conjunto de visitados, a DFS revisitará nós alcançáveis por vários caminhos e, em um grafo cíclico, entrará em loop infinito. Marcar um nó como visitado ao desempilhá-lo (e ignorar desempilhamentos já visitados) garante que cada nó seja processado uma vez e mantém o tempo de execução em O(V + E). Um erro comum é marcar os nós como visitados apenas ao desempilhar enquanto ainda se empilham duplicatas, o que é correto mas pode deixar entradas obsoletas na pilha que precisam ser ignoradas.
Coddy programming languages illustration

Domine algoritmos com a Coddy

COMEÇAR