백준에서 알고리즘을 풀다가 그래프 탐색에 대해서 문제를 직면 하였다. 감이 하나도 안잡히는 알고리즘으로 이번 기회에 학습하게 되어 정리해보고자 한다.
그래프 탐색은 DFS, BFS 두 알고리즘으로 해결할 수 있다고 한다. 내가 먼저 학습한 것은 깊이 우선 탐색인 DFS이다.
DFS란?
Depth First Search ( 깊이 우선 탐색 )의 약자로, 그래프 탐색에서 한 정점에서 출발하여 더 깊은 곳까지 탐색한 후 다른 경로를 탐색한다.
DFS 동작 방식
1. 시작 정점에서 출발한다.
2. 연결된 다른 정점으로 이동한다.
3. 더 이상 갈 곳이 없으면 이전 정점으로 되돌아온다.
4. 이 과정을 반복하여 모든 연결된 정점을 방문한다.
DeepDive
기본적인 개념은 확인했으니 이제 적용해보자.
우선 각 정점을 연결하는 정보를 저장할 배열이 필요하다.
static ArrayList<Integer>[] graph;
처음에 코드를 보고 의아했다. 이게 무슨의미인지 잘 이해가 안가는 생소한 자료구조였다.
이에 어떻게 내부 구조가 되는지 하나씩 넣어보면서 이해했다.
[
{}, // 0번 노드은 생략한다.
{}, // 1번 노드
{}, // 2번 노드
{}, // 3번 노드
{}, // 4번 노드
{} // 5번 노드
]
위와 같이 배열에는 하나의 ArrayList<Integer> 라는 객체가 저장되는 구조이다.
각 노드별로 연결된 간선을 입력받아서 노드별로 저장한다.
예를 들어
- 1 번은 2번 노드와 연결
- 1 번은 3번 노드와 연결
- 2번은 4번 노드와 연결
- 2번은 5번 노드와 연결
[
{2, 3},
{4, 5},
{},
{},
{},
]
이렇게 각 노드별로 연결된 노드를 저장하고 있다.
이제 위 노드들을 탐색하면서 노드를 이동하면서 검사한다.
먼저, 한 번 탐색했던 노드는 다시 탐색하지 않도록 flag 배열이 필요하다.
class Dfs{
static ArrayList<Integer>[] graph;
static boolean[] visited;
}
그래프 탐색
각 그래프를 탐색하기 위한 재귀 코드를 작성한다.
class Dfs {
static ArrayList<Integer>[] graph;
static boolean[] isVisited;
public staic void dfs(int node) {
isVisited[node] = true;
System.out.printf("now Visited node is : %d\n", node);
for (int next : graph[node]) {
if (!isVisited[next]) {
dfs(next);
}
}
}
Appled Problem
연결되어 있는 노드의 개수를 구하는 문제가 출제된다. 이를 위해서 하나의 변수에 count 횟수를 저장하면 된다.
class Viruns {
private static ArrayList<Integer>[] graph;
private static boolean[] visited;
private static int count;
private static void dfs(int node) {
visited[node] = true;
for (int next : graph[node]) {
if (!visited[next]) {
count++;
dfs(next);
}
}
}
}
Finish
한 번 경험한 것으로 모든 문제를 해결할 수는 없다.
학습한 기본적인 개념을 체득하여 다양한 문제를 해결하기 위해서 경험해보고 고민해보는 시간이 필요하다.