DFS는 깊이(Level)를 따라가며 탐색하지만, BFS는 Level 단위로 탐색
즉, “가장 가까운 노드 → 그다음 가까운 노드” 순서로 방문
procedure BFS(start):
create queue Q
mark start visited
enqueue (start, level=0) to Q
while Q not empty:
node, level ← dequeue
for each neighbor of node:
if not visited[neighbor]:
mark neighbor visited
enqueue (neighbor, level+1)
예시 그래프 (인접 리스트)
1 - 2 - 5
| |
3 4
코드
from collections import deque
# 그래프 (인접 리스트)
graph = {
1: [2, 3],
2: [1, 4, 5],
3: [1],
4: [2],
5: [2]
}
def bfs(start):
visited = set() # 방문한 노드 기록
q = deque([(start, 0)]) # (노드, level)
visited.add(start)
while q:
node, level = q.popleft()
print(f"노드 {node} 방문 (level={level})")
# branch: 현재 노드의 모든 이웃 탐색
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
q.append((neighbor, level+1))
bfs(1)
실행 흐름
노드 1 방문 (level=0)
노드 2 방문 (level=1)
노드 3 방문 (level=1)
노드 4 방문 (level=2)
노드 5 방문 (level=2)
Level: 시작점 1은 level=0, 이웃 노드들은 level=1, 그 다음은 level=2
Branch: 1번에서 2와 3으로 동시에 확장
❌ 오개념 1: BFS도 재귀로 구현할 수 있지 않나?
❌ 오개념 2: DFS와 BFS의 차이가 헷갈린다
❌ 오개념 3: 방문 체크 시점
코드
from collections import deque
def shortest_path(start, target, graph):
visited = {start: 0}
q = deque([start])
while q:
node = q.popleft()
if node == target:
return visited[node]
for neighbor in graph[node]:
if neighbor not in visited:
visited[neighbor] = visited[node] + 1 # 거리 갱신
q.append(neighbor)
return -1 # target에 도달 불가
graph = {
1: [2, 3],
2: [1, 4, 5],
3: [1],
4: [2],
5: [2]
}
print(shortest_path(1, 5, graph)) # 출력: 2
BFS의 level 정보 = 최단 거리임을 확인할 수 있음
백준 2178번 미로 탐색
→ BFS로 최단 경로를 구하는 대표 문제
백준 7562번 나이트의 이동
→ 체스판에서 나이트 이동 최단 횟수
백준 1697번 숨바꼭질
→ 1차원에서 BFS를 적용하는 기본기 문제