DFS 깊이 우선 탐색 (재귀방식)

DFS

 

 

1)  DFS란?

시작 노드에서 가능한 깊이까지 탐색한 뒤, 더 이상 갈 곳이 없으면 되돌아(backtrack) 하여 다음 경로를 탐색하는 방식입니다.


한 방향으로 계속 깊게 파고들며, 재귀 또는 스택(Stack)으로 구현 가능하고, 
경로 탐색, 조합 탐색, 미로 문제, 백트래킹 등에 유리합니다.

 

 

 

 

2)  DFS 시간복잡도와 공간복잡도

시간복잡도 : O(V + E)
V = 정점(노드)의 개수
E = 간선의 개수
공간복잡도 : O(V) 또는 O(h) 
V = 정점(노드)의 개수
h = 그래프의 최대 깊이

 

 

 

 

3)  DFS 활용분야

활용 분야 설명
경로 찾기 특정 노드까지의 경로 유무, 경로 목록 찾기
미로 탐색 출구가 있는지 확인하거나 모든 경로 탐색
백트래킹 문제 N-Queen, 순열/조합, 스도쿠 해결 등
트리 탐색 전위/중위/후위 순회 구현
사이클 탐지 그래프 내 순환 여부 확인
위상 정렬 DFS 기반 구현 가능 (방문 완료 시점 기록)
연결 요소 탐색 연결된 노드 그룹 찾기 (Connected Components)

 

 

 

4)  DFS 동작원리

/ 재귀 방식 /

1. 현재 노드를 방문 표시
2. 인접 노드를 하나씩 확인
3. 방문하지 않은 노드가 있으면 재귀적으로 계속 깊이 탐색
4. 더 이상 갈 곳이 없으면 한 단계 위로 되돌아감

 

 

 

 

5)  예시를 통한 동작원리 설명

 

 

STEP 0: Call Stack = ['A']

시작 노드 A가 호출됨

아직 아무 자식도 탐색하지 않은 상태

다음에 B → C 순서로 탐색 예정 (A의 자식 순서)


 

 

 

STEP 1: Call Stack = ['A', 'B']

A에서 B로 이동

B는 A의 첫 번째 자식 → DFS는 "깊이 우선"이므로 바로 이동

B의 자식 D → E 중에서 D로 먼저 가게 됨

 

 

STEP  Step 2: Call Stack = ['A', 'B', 'D']

B에서 D로 이동

현재 가장 깊은 곳까지 내려온 상태

D는 자식이 없기 때문에 이후 스택이 빠지기 시작함 (백트래킹)

 

 

STEP 3: Call Stack = ['A', 'B', 'E']

D 호출이 끝나고, 다시 B로 백트래킹

이제 B의 두 번째 자식 E 호출

E도 자식 없음 → 곧 B 함수도 종료되고 다시 A로 돌아감

 

 

STEP 4: Call Stack = ['A', 'C']

B까지 모두 종료 → A로 백트래킹 후

A의 두 번째 자식 C 호출

이제 C의 자식들로 깊게 내려갈 차례

 

 

STEP 5: Call Stack = ['A', 'C', 'F']

C에서 F 호출 (첫 번째 자식)

자식 없음 → 곧 G로 넘어감

 

 

STEP 6: Call Stack = ['A', 'C', 'G']

F 호출 종료 → C로 백트래킹 → G 호출

G도 자식 없음 → 전체 DFS 종료

 

 

6)  Java로 구현한 DFS 예제 코드

import java.util.*;

public class RecursiveDFS {

    // 인접 리스트로 그래프 표현
    private Map<String, List<String>> graph = new HashMap<>();

    // 간선 추가 함수
    public void addEdge(String node, String neighbor) {
        graph.computeIfAbsent(node, k -> new ArrayList<>()).add(neighbor);
    }

    // DFS 재귀 함수
    public void dfs(String node, Set<String> visited) {
        visited.add(node);
        System.out.println("Visiting: " + node);

        for (String neighbor : graph.getOrDefault(node, new ArrayList<>())) {
            if (!visited.contains(neighbor)) {
                dfs(neighbor, visited);
            }
        }
    }

    public static void main(String[] args) {
        RecursiveDFS dfs = new RecursiveDFS();

        // 그래프 구성
        dfs.addEdge("A", "B");
        dfs.addEdge("A", "C");
        dfs.addEdge("B", "D");
        dfs.addEdge("B", "E");
        dfs.addEdge("C", "F");
        dfs.addEdge("C", "G");

        // 방문 집합 생성 및 DFS 실행
        Set<String> visited = new HashSet<>();
        System.out.println("DFS traversal:");
        dfs.dfs("A", visited);
    }
}

 

// 출력결과 //
DFS traversal:
Visiting: A
Visiting: B
Visiting: D
Visiting: E
Visiting: C
Visiting: F
Visiting: G

 

 

 

 

 

 

 

'Algorithm > 이론' 카테고리의 다른 글

순열 / 조합 / 부분집합  (0) 2025.05.02
재귀함수 (Recursion)  (0) 2025.05.02
DFS 깊이 우선 탐색 (스택 방식)  (0) 2025.05.01
복잡도  (0) 2025.05.01
BFS 너비 우선 탐색  (0) 2025.04.30