🎯 Algoritmo de Busca em Profundidade em Python
Em poucas palavras
Note que os nós são explorados na ordem inversa em que foram adicionados ao dicionário, pois a estrutura de pilha remove sempre o último elemento inserido (
stack.pop()).
📝 Notas e Desenvolvimento
🔗 Conexões e Contexto
- Atlas: MdC - Programação
- Notas Relacionadas:
- Conceitos:
- Algoritmo de busca em largura
- Teoria dos Grafos
- Pilhas - LIFO
- Recursão
- Conceitos:
📚 Referências e Fontes
Links Externos
Citações Diretas
📂 Outros Conteúdos Preservados
Busca em Profundidade (DFS) em Python
Abaixo está a implementação padrão do Algoritmo de busca em profundidade utilizando a Python. Esta versão utiliza uma estrutura de dados de Pilha (stack) iterativa para simular o comportamento de recursão do algoritmo.
Python
def dfs(tree: Dict[str, List[str]], start: str, end: str) -> Optional[List[str]]:
"""Implementa o algoritmo DFS iterativo de forma otimizada utilizando uma
pilha e rastreamento de nós visitados.
Args:
tree (Dict[str, List[str]]): Lista de adjacência representando o grafo
ou árvore.
start (str): O vértice inicial de exploração.
end (str): O vértice destino.
Retorna:
Optional[List[str]]: O caminho do início ao fim se encontrado, senão
None.
"""
if start == end:
return [start]
# Estruturas para otimização de performance
stack: List[str] = [start]
visited: Set[str] = {start}
# Dicionário para reconstruir o caminho eficiente: {nó_filho: nó_pai}
parent_map: Dict[str, str] = {}
while stack:
vertex = stack.pop()
if vertex == end:
# Reconstrói o caminho de trás para frente a partir do parent_map
path = []
current = end
while current != start:
path.append(current)
current = parent_map[current]
path.append(start)
return path[::-1] # Inverte para o sentido correto (start -> end)
# Processa os vizinhos na ordem inversa para manter o padrão visual de exploração (Esquerda -> Direita)
for neighbor in reversed(tree.get(vertex, [])):
if neighbor not in visited:
visited.add(neighbor)
parent_map[neighbor] = vertex
stack.append(neighbor)
return None💻 Exemplo de Execução e Resposta
Para testar o algoritmo, definimos uma estrutura de árvore enraizada em A utilizando um dicionário, onde o objetivo final é encontrar o caminho até o nó K. A exemplo do grafo a seguir:
graph TD A --> B A --> C A --> D B --> E C --> F C --> G D --> H E --> I E --> J F --> K
### Representação da estrutura em árvore
tree: Dict[str, List[str]] = {
"A": ["B", "C", "D"],
"B": ["E"],
"C": ["F", "G"],
"D": ["H"],
"E": ["I", "J"],
"F": ["K"],
"G": [],
"H": [],
"I": [],
"J": [],
"K": [],
}
caminho_encontrado = dfs(tree, "A", "K")
print(f"Caminho final: {caminho_encontrado}")📄 Saída do Terminal
Comportamento da Pilha (LIFO)
Note que os nós são explorados na ordem inversa em que foram adicionados ao dicionário, pois a estrutura de pilha remove sempre o último elemento inserido (
stack.pop()).
Explorando nó A
Nós adjacentes descobertos: C B D
Explorando nó D
Nós adjacentes descobertos: H
Explorando nó H
Nó folha ou sem novas ramificações.
Explorando nó B
Nós adjacentes descobertos: E
Explorando nó E
Nós adjacentes descobertos: I J
Explorando nó J
Nó folha ou sem novas ramificações.
Explorando nó I
Nó folha ou sem novas ramificações.
Explorando nó C
Nós adjacentes descobertos: G F
Explorando nó F
Nós adjacentes descobertos: K
Explorando nó K
Caminho final: ['A', 'C', 'F', 'K']