Searching in trees and graphs is a fundamental operation used in many applications such as pathfinding, network analysis, and hierarchical data processing. The most common search techniques include Depth-First Search (DFS) and Breadth-First Search (BFS).
DFS explores as far as possible along each branch before backtracking, which is suitable for pathfinding and connectivity checking.
def dfs(graph, node, visited=None):
if visited is None:
visited = set()
visited.add(node)
print(node, end=' ')
for neighbor in graph.get(node, []):
if neighbor not in visited:
dfs(graph, neighbor, visited)
# Usage
graph = {
'A': ['B', 'C'],
'B': ['D', 'E'],
'C': ['F'],
'D': [],
'E': ['F'],
'F': []
}
dfs(graph, 'A')
BFS explores neighbor nodes at the current depth before moving on to nodes at the next depth level, useful for shortest path finding in unweighted graphs.
from collections import deque
def bfs(graph, start):
visited = set()
queue = deque([start])
visited.add(start)
while queue:
node = queue.popleft()
print(node, end=' ')
for neighbor in graph.get(node, []):
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
# Usage
bfs(graph, 'A')
Graph search algorithms differ from tree search as they handle cycles and repeated states by maintaining visited or explored sets to avoid infinite loops and redundant processing.