깊이 우선 탐색(DFS)으로 그래프를 탐색해보자.
하나의 정점으로 시작하여, 차례대로 모든 정점을 한 번씩 방문하는 것이다.
특정 도시에서 다른 도시로 갈 수 있는지 없는지, 전자 회로에서 특정 단자와 단자가 서로 연결되어 있는지 알아볼 수 있다.
DFS는 탐색에서 깊은 것을 우선적으로 탐색하는 알고리즘이다.
너비 우선 탐색 (BFS)는 큐(queue)가 사용되지만, 깊이 우선 탐색 (DFS)는 스택(stack)이 사용된다.
사실 컴퓨터는 함수 호출을 스택의 원리를 사용하기 때문에, 재귀를 사용하면 DFS를 구현할 수 있다.
아래와 같은 그래프가 있을 때, DFS로 방문해 보자.
노드 | 연결된 노드 |
---|---|
1 | 2, 3, 4 |
2 | 1, 4 |
3 | 1, 4 |
4 | 1, 2, 3 |
다음은 그래프의 방문 순서를 표현한 것이다.
노란색은 현재 탐색하는 노드, 회색은 이미 방문한 노드, 하얀색은 방문하지 않은 노드다.
노드 1을 탐색하였으므로 방문 처리한다.
연결된 2, 3, 4는 전부 방문 하지 않았다. 그 중에서 먼저 2번 부터 탐색할 것이다. (2)로 진행한다.
노드 2를 탐색하였으므로 방문 처리한다.
2와 연결된 1과 4번 노드중, 1번 노드는 이미 방문했으므로 탐색하지 않고, 4번을 탐색할 것이다. (3)으로 진행한다.
노드 4를 탐색하였으므로 방문 처리한다.
4와 연결된 1, 2, 3번 노드중, 1, 2번 노드는 이미 방문했으므로 탐색하지 않고, 3번을 탐색할 것이다. (4)로 진행한다.
노드 3을 탐색하였으므로 방문 처리한다.
3과 연결된 1, 4노드 모두 방문했으므로 탐색을 종료한다.
위와 같은 알고리즘을 자바스크립트 코드로 작성하면 다음과 같다.
function DFS을 참고하면 된다.
function solution(n, m, v, road) {
let graph = Array.from(Array(n + 1), () => Array());
let ch = Array(n + 1).fill(0);
let answer = [];
// 연결된 노드 표시하기
for (let i = 0; i < m; i++) {
graph[road[i][0]].push(road[i][1]);
graph[road[i][1]].push(road[i][0]);
}
// 연결된 노드를 오름차순으로 정렬하기
for (let i = 1; i <= n; i++) {
graph[i].sort((a, b) => a - b);
}
function DFS(L) {
// 방문한 노드면 탈출
if (ch[L] === 1) return;
else {
// 방문하지 않았다면 인접한 노드 방문하기
ch[L] = 1;
answer.push(L);
for (let node of graph[L]) {
DFS(node);
}
}
}
DFS(v);
return answer;
}
console.log(
solution(4, 5, 1, [
[1, 2],
[1, 3],
[1, 4],
[2, 4],
[3, 4],
])
); // [ 1, 2, 4, 3 ]
console.log(
solution(5, 5, 3, [
[5, 4],
[5, 2],
[1, 2],
[3, 4],
[3, 1],
])
); // [ 3, 1, 2, 5, 4 ]
console.log(
solution(1000, 1, 1000, [
[999, 1000],
[999, 1000],
])
); // [ 1000, 999 ]
참고 링크
https://gmlwjd9405.github.io/2018/08/14/algorithm-dfs.html
https://blog.naver.com/ndb796/221230945092