DFS와 BFS
1. 깊이 우선 탐색 (Depth First Search)
01. 정의
- 그래프의 모든 정점을 발견하는 가장 단순하고 고전적인 방법
- 현재 정점과 인접한 간선들을 하나씩 검사하다가, 아직 방문하지 않은 정점으로 향하는 간선이 있다면 그 간선을 무조건 따라간다. 이 과정에서 더이상 갈 곳이 없는 막힌 정점에 도달하면 포기하고, 마지막에 따라왔던 간선을 따라 뒤로 돌아간다.
02. 과정
03. 특징
- 탐색의 각 과정에서 가능한 한 그래프 안으로 ‘깊이’ 들어가려고 시도하며, 막힌 정점에 도달하지 않는 한 뒤로 돌아가지 않는다.
- 더 따라갈 간선이 없을 경우 이전으로 돌아간다. 이를 구현하기 위해서 순환(재귀) 알고리즘 형태로 되어 있다.
- 그래프가 인접 리스트로 표현되어 있다면 시간 복잡도가 O(n + e)이고, 인접 행렬로 표시되어 있다면 O(n^2)이다. (n은 정점(v)을 의미, e는 간선을 의미)
04. 구현
const v = [1, 2, 3, 4, 5];
const e = [
[1, 2],
[1, 5],
[2, 5],
[2, 3],
[3, 4],
[2, 4],
[4, 5],
];
const list = Array.from({length: v.length + 1}, () => []);
for (let i = 0; i < e.length; i++) {
const from = e[i][0];
const to = e[i][1];
list[from].push(to);
list[to].push(from);
}
// 이전 시간에 구현한 인접 리스트를 이용해서 DFS를 구현해보겠습니다.
const visited = Array.from({length: v.length + 1}, () => false);
const dfs = (nowVertex) => {
visited[nowVertex] = true;
for (let i = 0; i < list[nowVertex].length; i++) {
const nextVertex = list[nowVertex][i];
if (visited[nextVertex]) continue;
dfs(nextVertex);
}
};
dfs(1);
// 1, 2, 5, 4, 3
2. 너비 우선 탐색 (Breadth First Search)
01. 정의
- 시작 정점에서 가까운 정점부터 순서대로 방문하는 탐색 알고리즘이다.
02. 과정
03. 특징
- 두 정점을 연결하는 경로 중 최단 경로를 찾을 때 사용한다.
- 큐를 이용하여 구현하며, 시작점에서 가까이 있는 정점이 큐에 먼저 추가되고, 멀리 있는 정점이 큐에 나중에 추가된다.
- DFS와 동일하게, 그래프가 인접 리스트로 표현되어 있다면 시간 복잡도가 O(n + e)이고, 인접 행렬로 표시되어 있다면 O(n^2)이다.
04. 구현
// 이전 시간에 구현한 인접 리스트를 이용해서 BFS를 구현해보겠습니다.
const visited = Array.from({length: v.length + 1}, () => false);
const queue = [];
visited[1] = true;
queue.push(1);
while (queue.length) {
const nowVertex = queue.shift();
for (let i = 0; i < list[nowVertex].length; i++) {
const nextVertex = list[nowVertex][i];
if (visited[nextVertex]) continue;
visited[nextVertex] = true;
queue.push(nextVertex);
}
}
3. 출처
- C언어로 쉽게 풀어쓴 자료구조 (천인국, 공용해, 하상호 지음)
- 프로그래밍 대회에서 배우는 알고리즘 문제 해결 전략 (구종만 지음)