Menu
Coddy logo textTech

너비 우선 탐색 (BFS)

마지막 업데이트

너비 우선 탐색은 그래프를 레벨 단위로 탐색합니다. 시작 노드에서 출발해 먼저 그 노드의 모든 인접 이웃을 방문하고, 그다음 그 이웃들의 방문하지 않은 이웃을 모두 방문하며, 이런 식으로 진행하여 - 거리가 커지는 고리 형태로 바깥쪽으로 확장합니다. 위의 재생을 누르면 시작 노드에서 한 층씩 퍼져 나가는 모습을 볼 수 있습니다.

BFS는 선입선출 큐를 사용하며, 이것이 레벨 단위 순서를 강제합니다. 홉 거리 순서로 노드에 도달하기 때문에, BFS는 가중치가 없는 그래프에서 최단 경로(가장 적은 간선)를 찾습니다. 각 노드와 간선을 한 번씩 방문하므로 O(V + E) 시간에 동작합니다.

시간 및 공간 복잡도

측정 항목복잡도비고
시간O(V + E)각 정점과 간선을 한 번씩 방문
공간O(V)큐 + 방문 집합, 최악의 경우 모든 노드
순회레벨 단위가장 가까운 노드부터, 고리 형태로
최단 경로예 (가중치 없음)가장 적은 간선으로 각 노드에 도달

단계별 진행

단계무슨 일이 일어나는가
1시작 노드를 큐에 넣는다.
2맨 앞 노드를 큐에서 꺼내고 방문했다고 표시한다.
3그 노드의 각 이웃을 살펴본다.
4아직 방문하지 않았고 큐에도 없는 이웃을 큐에 넣는다.
5큐가 빌 때까지 반복한다.

풀이 예제

노드 0에서 이 그래프를 순회하며, 여기서 0-1, 0-2, 1-3, 2-3, 2-4는 간선이다:

단계방문큐 (프런티어)
시작{}[0]
0 꺼냄{0}[1, 2]
1 꺼냄{0, 1}[2, 3]
2 꺼냄{0, 1, 2}[3, 4]
3 꺼냄{0, 1, 2, 3}[4]
4 꺼냄{0, 1, 2, 3, 4}[] (완료)

BFS를 사용해야 할 때

사용할 때피해야 할 때
가중치가 없는 그래프에서 최단 경로가 필요할 때간선에 가중치가 있을 때 - 대신 Dijkstra를 사용
목표가 시작점 근처에 있을 가능성이 높을 때그래프가 매우 넓을 때 - 큐가 거대한 프런티어를 담을 수 있음
그래프를 레벨 순서로 탐색하고 싶을 때임의의 노드에 도달하기만 하면 될 때, DFS가 메모리를 덜 사용
연결 요소나 최소 홉 경로를 찾을 때위상 정렬이나 사이클 탐지가 필요할 때 - DFS가 더 적합

Breadth-First Search 코드

Python, JavaScript, Java, C++, C로 작성된 깔끔하고 실행 가능한 Breadth-First Search 구현입니다. 언어를 선택해 코드를 복사하거나 Coddy 플레이그라운드에서 바로 열어보세요.

Python로 구현한 Breadth-First Search 코드

Python
1from collections import deque2
3
4def bfs(graph, start):5    visited = {start}6    queue = deque([start])7    order = []8    while queue:9        node = queue.popleft()10        order.append(node)11        for neighbor in graph[node]:12            if neighbor not in visited:13                visited.add(neighbor)  # mark on enqueue, not dequeue14                queue.append(neighbor)15    return order16
17
18graph = {19    "A": ["B", "C"],20    "B": ["D", "E"],21    "C": ["F"],22    "D": [],23    "E": ["F"],24    "F": [],25}26
27print("BFS order:", " -> ".join(bfs(graph, "A")))
이 코드를 Python 플레이그라운드에서 실행하기

너비 우선 탐색 자주 묻는 질문

BFS의 시간 복잡도는 얼마인가요?
BFS는 O(V + E) 시간에 동작하며, 여기서 V는 정점의 수, E는 간선의 수입니다. 각 정점을 한 번 방문하고 각 간선을 한 번 살펴보기 때문입니다. 큐와 방문 집합을 위해 O(V)의 공간을 사용합니다.
BFS는 최단 경로를 찾나요?
예, 가중치가 없는 그래프에서 찾습니다. BFS는 시작점으로부터 홉 거리 순서로 노드에 도달하므로, 어떤 노드에 처음 도달하는 것은 간선 수가 가장 적은 경로를 통해서입니다. 가중치가 있는 그래프에서는 대신 Dijkstra 알고리즘이 필요합니다.
BFS와 DFS의 차이는 무엇인가요?
BFS는 큐를 사용해 레벨 단위(가까운 것부터)로 탐색하고, DFS는 스택을 사용해 한 가지를 따라 깊이 들어간 뒤 되돌아옵니다. BFS는 가중치 없는 최단 경로를 찾고, DFS는 넓은 그래프에서 메모리를 덜 사용하며 사이클 탐지와 위상 정렬에 적합합니다.
Dijkstra 알고리즘 대신 BFS를 언제 사용해야 하나요?
모든 간선의 비용이 같을 때 BFS를 사용하세요. 우선순위 큐 없이 O(V + E) 시간에 간선 수가 가장 적은 경로를 찾기 때문입니다. 간선에 서로 다른 가중치가 있을 때는 Dijkstra 알고리즘이 필요하며, 가중치 그래프에 순수한 BFS를 실행하면 최소 비용이 아니라 최소 홉 경로가 나옵니다.
BFS에는 왜 방문 집합이 필요한가요?
그래프에는 사이클이 있을 수 있어서, 방문 집합이 없으면 BFS가 같은 노드를 반복해서 큐에 넣어 무한히 반복하게 됩니다. 노드를 처음 큐에 넣을 때(꺼낼 때가 아니라) 표시하면, 같은 노드가 서로 다른 이웃에 의해 큐에 두 번 추가되는 것도 방지됩니다.
노드를 큐에 넣을 때와 꺼낼 때 중 언제 방문으로 표시해야 하나요?
큐에 넣을 때 표시하세요. 꺼낼 때까지 기다리면, 처리되기 전에 같은 노드가 서로 다른 이웃에 의해 큐에 여러 번 추가되어 메모리와 시간을 낭비합니다. 넣을 때 표시하면 각 노드가 정확히 한 번만 큐에 들어가는 것이 보장됩니다.
Coddy programming languages illustration

Coddy로 알고리즘을 마스터하세요

시작하기