1. 깊이 우선 탐색(DFS) 개요
- 깊이 우선 탐색(Depth-First Search, DFS)은 그래프나 트리 구조에서 가능한 한 깊이 들어가면서 탐색을 진행하는 알고리즘입니다.
- 미로 찾기를 할 때 한 방향으로 계속 가다가 막히면 다시 돌아와서 다른 방향으로 가는 것과 유사합니다.
1.1 DFS의 특징
- 한 경로를 끝까지 탐색한 후 다음 경로로 이동
- 재귀 함수나 스택으로 구현 가능
- 백트래킹이 필요한 문제에 적합
- 모든 노드를 방문하는 것이 목표일 때 사용
2. DFS 동작 원리
2.1 기본 알고리즘
- 시작 노드를 방문 처리
- 현재 노드와 연결된 미방문 노드를 찾아 방문
- 더 이상 방문할 노드가 없으면 이전 노드로 돌아감
- 모든 노드를 방문할 때까지 2-3 반복
DFS vs BFS
DFS는 깊이를 우선으로 하는 반면, BFS(너비 우선 탐색)는 너비를 우선으로 탐색합니다. 미로에서 DFS는 한 길을 끝까지 가보는 전략이고, BFS는 현재 위치에서 갈 수 있는 모든 길을 한 칸씩 가보는 전략입니다.
3. DFS 구현 방법
3.1 재귀를 이용한 구현
기본 구조
def dfs(graph, v, visited):
# 현재 노드를 방문 처리
visited[v] = True
print(v, end=' ')
# 현재 노드와 연결된 다른 노드를 재귀적으로 방문
for i in graph[v]:
if not visited[i]:
dfs(graph, i, visited)
# 그래프를 인접 리스트로 표현
graph = [
[], # 0번 노드는 사용하지 않음
[2, 3, 8], # 1번 노드와 연결된 노드들
[1, 7], # 2번 노드와 연결된 노드들
[1, 4, 5], # 3번 노드와 연결된 노드들
[3, 5], # 4번 노드와 연결된 노드들
[3, 4], # 5번 노드와 연결된 노드들
[7], # 6번 노드와 연결된 노드들
[2, 6, 8], # 7번 노드와 연결된 노드들
[1, 7] # 8번 노드와 연결된 노드들
]
# 방문 여부를 저장할 리스트
visited = [False] * 9
# DFS 호출
dfs(graph, 1, visited) # 1번 노드부터 탐색 시작
3.2 스택을 이용한 구현
반복문 구조
def dfs_iterative(graph, start):
visited = []
stack = [start]
while stack:
v = stack.pop()
if v not in visited:
visited.append(v)
stack.extend(reversed(graph[v]))
return visited
4. DFS 활용 사례
4.1 미로 탐색 문제
def solve_maze(maze, start, end):
def dfs(x, y):
if x < 0 or x >= len(maze) or y < 0 or y >= len(maze[0]):
return False
if maze[x][y] == 1: # 길이 있는 경우
maze[x][y] = 0 # 방문 처리
# 상하좌우 탐색
dfs(x-1, y)
dfs(x+1, y)
dfs(x, y-1)
dfs(x, y+1)
return True
return False
return dfs(start[0], start[1])