Ch.7 그래프
BFS — 너비 우선 탐색, 최단거리의 열쇠
물결이 퍼지듯 한 겹씩 탐색한다
연못에 돌을 던지면 물결이 동심원으로 퍼집니다. BFS도 마찬가지 — 시작점에서 거리 1인 노드 → 거리 2인 노드 → ... 순서로 탐색합니다.
DFS처럼 깊이 파고들면 안 될까? 왜 한 겹씩 탐색해야 하지?
한 겹씩 탐색하기 때문에 처음 도착한 경로가 곧 최단 경로입니다. 이것이 BFS의 핵심 강점입니다.
핵심 개념
BFS(너비 우선 탐색)
시작점에서 가까운 순서대로 탐색
레벨(Level)
시작점에서의 거리(엣지 수) 기준 층
핵심 내용
최단거리를 구하는 가장 확실한 무기, BFS
DFS는 스택(LIFO) → 깊이 우선 BFS는 큐(FIFO) → 너비 우선
"최단"이라는 키워드가 보이면 99% BFS입니다!
파이썬에서 BFS는 deque로 구현합니다
from collections import deque
def bfs(graph, start):
visited = set([start])
queue = deque([start])
while queue:
node = queue.popleft() # FIFO — 가장 먼저 넣은 것
print(node, end=' ')
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
return visited
graph = {'A':['B','C'], 'B':['A','D'], 'C':['A','D'], 'D':['B','C']}
bfs(graph, 'A') # A B C DDFS vs BFS 코드 차이 딱 하나! DFS: `stack.pop()` — 마지막에 넣은 것 먼저 BFS: `queue.popleft()` — 먼저 넣은 것 먼저 나머지 구조는 완전히 동일합니다
면접관이 "list.pop(0)" 쓰면 감점합니다. O(n)이니까요. deque.popleft()는 O(1)!
BFS로 시작점에서 각 노드까지 최단 거리를 구합니다
from collections import deque
def shortest_distance(graph, start):
dist = {start: 0}
queue = deque([start])
while queue:
node = queue.popleft()
for neighbor in graph[node]:
if neighbor not in dist:
dist[neighbor] = dist[node] + 1
queue.append(neighbor)
return dist
graph = {0:[1,2], 1:[0,3], 2:[0,3], 3:[1,2,4], 4:[3]}
print(shortest_distance(graph, 0))
# {0:0, 1:1, 2:1, 3:2, 4:3}`dist[neighbor] = dist[node] + 1` 이 한 줄이 BFS 최단거리의 전부입니다
BFS는 가중치가 동일한(=1) 그래프에서만 최단거리를 보장합니다. 가중치가 다르면 다익스트라를 써야 합니다
BFS가 레벨별로 탐색하는 과정을 추적합니다
Level 0: A → Level 1: B, C → Level 2: D 가까운 노드부터 처리됩니다
면접에서 "레벨별로"라는 키워드가 나오면 이 패턴!
def bfs_by_level(graph, start):
visited = set([start])
queue = deque([start])
level = 0
while queue:
size = len(queue) # 현재 레벨의 노드 수
print(f'Level {level}:', end=' ')
for _ in range(size): # 현재 레벨만 처리
node = queue.popleft()
print(node, end=' ')
for nb in graph[node]:
if nb not in visited:
visited.add(nb)
queue.append(nb)
print()
level += 1핵심은 `for _ in range(len(queue))`. 루프 시작 시점의 queue 크기만큼만 처리하면 한 레벨입니다
가중치가 없는 그래프에서 A→D 최단거리를 구하려면 어떤 알고리즘?
파이썬에서 BFS를 구현할 때 list.pop(0) 대신 deque.popleft()를 쓰는 이유는 시간 복잡도 때문이다
BFS 정복 완료!
핵심 용어
BFS
Breadth-First Search — 너비 우선 탐색
큐(Queue)
FIFO — 먼저 넣은 것을 먼저 꺼냄
최단 거리
가중치 없는 그래프에서 BFS = 최단 경로
정리 노트
너비 우선 탐색 (BFS)
핵심 패턴
- BFS 기본
- `deque([start])` → `popleft()` → 이웃 append
- 최단 거리
- `dist[nb] = dist[node] + 1`
- 레벨 탐색
- `for _ in range(len(queue))`로 레벨 구분
DFS vs BFS
- DFS
- 스택/재귀 — 경로 탐색, 연결 요소
- BFS
- 큐 — 최단거리, 레벨별 탐색
'최단'이라는 키워드가 보이면 BFS! deque.popleft()는 필수!
시각 자료
핵심 정리
- 1BFS = 큐(FIFO)로 가까운 순서대로 탐색
- 2가중치 없는 그래프에서 BFS = 최단거리
- 3deque.popleft() O(1) vs list.pop(0) O(n)
퀴즈와 인터랙션으로 더 깊이 학습하세요
play_circle인터랙티브 레슨 시작