DFS,BFS 알고리즘
09 Mar 2021그래프 탐색
하나의 정점으로부터 시작하여 차례로 모든 정점을 한번씩 방문하는 것
깊이 우선 탐색
깊이 우선 탐색이란
그래프 전체를 탐색하는 방법중 하나로써 시작점부터 다음 분기점으로 넘어가기 전에 해당 분기를 완벽하게 탐색하고 넘어가는 방법이다. 갈림길을 만났을 때, 한 방향으로 끝까지 간 이후에 돌아와서 다른 방향으로 끝까지 가보는 것과 유사하다.
사용시 장점
- 현재 경로 위에 있는 노드들만 방문배열에 저장하면 되므로 메모리가 비교적 적게 사용된다.
- 모든 노드를 탐색해볼 때 유용하다.
- 구현이 너비 우선 탐색(BFS)보다 비교적 간단하다.
사용시 유의 사항
- 목표로 하는 값을 구하면 탐색을 종료하므로 이 값이 최소값(최단 경로)이 된다는 보장이 없다.
- 재귀의 형태를 띄고 있기에 노드의 방문 여부를 확인하지 않으면 무한 루프에 빠질 위험이 있디.
활용 문제
DFS 수도 코드 구현
코드 펼치기
void search(Node root) {
// 더이상 갈 수 있는 노드가 없으면 return
if (root == null) return;
// 1. root 노드 방문하여 작업
do(root);
visited[root] = true; // 1-1. 방문한 노드를 표시
// 2. root 노드와 인접한 정점을 모두 방문
for each (Node n in adjacent[root]) {
if (visited[n] == false) { // 4. 방문하지 않은 정점을 찾는다.
search(n); // 3. root 노드와 인접한 정점 정점을 시작 정점으로 DFS를 시작
}
}
}
넓이 우선 탐색
넓이 우선 탐색이란
루트 노드(혹은 다른 임의의 노드)에서 시작허여 가까운 노드를 먼저 탐색하고 멀리 떨어져있는 노드를 나중에 방문하는 방법이다.
사용시 장점
- 두 노드 사이의 최단 경로를 찾을 때 이 방법을 사용한다.
- Prim, Dijkstra 알고리즘과 유사하다.
사용시 유의 사항
- 단계별로 탐색하기 때문에 직관적이지 못하다.
- 노드의 방문 여부를 확인하지 않으면 무한 루프에 빠질 위험이 있다.
활용 문제
BFS 수도코드 구현
코드 펼치기
void search(Node root) {
Queue queue = new Queue();
visited[root] = true; // (방문한 노드 체크)
queue.enqueue(root); // 1-1. 큐의 끝에 추가
// 3. 큐가 소진될 때까지 계속한다.
while (!queue.isEmpty()) {
Node now = queue.dequeue(); // 큐의 앞에서 노드 추출
do(now); // 2-1. 큐에서 추출한 노드 방문하여 작업
// 2-2. 큐에서 꺼낸 노드와 인접한 노드들을 모두 차례로 방문한다.
foreach (Node n in adjacent[now]) {
if (visited[n] == false) {
visited[n] = true; // (방문한 노드 체크)
queue.enqueue(n); // 2-3. 다음 노드 큐의 끝에 추가
}
}
}
}
참고자료
https://www.geeksforgeeks.org/depth-first-search-or-dfs-for-a-graph/ https://www.geeksforgeeks.org/breadth-first-search-or-bfs-for-a-graph/ https://www.freelancinggig.com/blog/2019/02/06/what-is-the-difference-between-bfs-and-dfs-algorithms/