Problem Solving/Algorithm
[알고리즘] DFS(깊이 우선 탐색)
se0m
2021. 6. 5. 01:11
DFS (Depth-First Search) 깊이 우선 탐색
DFS는 그래프 탐색 알고리즘 중 하나로
시작 노드에서 가능한 깊이까지 먼저 탐색한 뒤
더 이상 깊게 갈 곳이 없을 경우 되돌아가며(Backtracking) 탐색을 이어가는 방식입니다.
DFS 특징
- 방문 경로를 깊이 우선으로 추적
- 재귀 호출 또는 스택(Stack)을 활용해 구현 가능
- 그래프의 연결 요소 탐색에 유용
- 순환 구조(사이클)나 미로 찾기 문제 등에 자주 사용됨
DFS vs BFS
| 구분 | DFS | BFS |
| 자료구조 | 스택(Stack) or 재귀 | 큐(Queue) |
| 방문 순서 | 깊이 우선 → 다음 분기로 이동 | 너비 우선 → 레벨 순서대로 이동 |
| 구현 방식 | 주로 재귀 또는 수동 스택 | 큐로 구현 |
| 사용 예시 | 백트래킹, 미로, 트리 탐색 등 | 최단 거리, 레벨 기반 탐색 등 |
DFS 알고리즘 구현
DFS는 다음과 같은 구조로 동작합니다:
- 시작 노드를 needVisit 스택에 넣음
- 스택에서 노드를 꺼내고, 아직 방문하지 않았다면 visited 목록에 추가
- 해당 노드의 인접 노드를 다시 needVisit 스택에 넣음
- 반복
BFS는 두 개의 큐를 활용하는데 반해
DFS는 스택과 큐를 활용한다는 차이가 있음을 인지해야 함
Java 코드
import java.util.*;
public class DFSExample {
public static List<String> dfs(Map<String, List<String>> graph, String startNode) {
List<String> visited = new ArrayList<>();
Stack<String> needVisit = new Stack<>();
needVisit.push(startNode);
while (!needVisit.isEmpty()) {
String node = needVisit.pop();
if (!visited.contains(node)) {
visited.add(node);
List<String> neighbors = graph.getOrDefault(node, new ArrayList<>());
// 뒤에 있는 노드가 먼저 방문되도록 역순으로 push
List<String> reversed = new ArrayList<>(neighbors);
Collections.reverse(reversed);
for (String neighbor : reversed) {
needVisit.push(neighbor);
}
}
}
return visited;
}
public static void main(String[] args) {
Map<String, List<String>> graph = new HashMap<>();
graph.put("A", Arrays.asList("B", "C"));
graph.put("B", Arrays.asList("D", "G"));
graph.put("C", Arrays.asList("E", "F"));
graph.put("D", Arrays.asList("G"));
graph.put("E", new ArrayList<>());
graph.put("F", new ArrayList<>());
graph.put("G", Arrays.asList("H", "I"));
graph.put("H", new ArrayList<>());
graph.put("I", Arrays.asList("J"));
graph.put("J", new ArrayList<>());
List<String> result = dfs(graph, "A");
System.out.println("DFS 탐색 결과: " + result);
}
}
시간 복잡도
DFS의 시간 복잡도는 다음과 같이 계산됩니다:
- 노드 수(V): 각 노드를 한 번씩 방문
- 간선 수(E): 각 간선을 한 번씩 탐색
- 위 코드에서 `while (!needVisit.isEmpty())`은 `V + E` 번 만큼 수행함
따라서 시간 복잡도는 `O(V + E)` 입니다.
DFS 요약
| 항목 | 설명 |
| 구현 방식 | 재귀 or 스택 |
| 탐색 순서 | 깊이 우선 (Backtracking) |
| 시간 복잡도 | `O(V + E)` |
| 용도 | 사이클 탐지, 경로 탐색, 백트래킹 등 |