Computer Science/Data_Structure

깊이 우선 탐색(DFS) 란?

백엔드 규니 2020. 1. 4. 00:36
728x90
반응형

그래프의 탐색

그래프 탐색은 가장 기본적인 연산으로서 하나의 정점으로부터 시작하여 차례대로 모든 정점들을 한 번씩 방문하는 것이다. 그래프 탐색은 아주 중요하다 

 

  • 도시를 연결하는 그래프가 있을 때, 특정 도시에서 다른 도시로 갈 수 있는지 없는지는 탐색하여 체크

 

그래프의 탐색 방법은 깊이 우선 탐색너비 우선 탐색의 두 가지가 있다.

이 글에서는 깊이 우선 탐색에 대하여 알아보겠다.

 

 

 

깊이 우선탐색(DFS : depth first search) 

  • 트리에서 생각하면 이해하기 쉽다(트리도 그래프의 일종이라는 점을 명심하자)

  • 트리를 탐색할 때 시작 정점에서 한 방향으로 계속 가다가 더 이상 갈 수 없게 되면 다시 가장 가까운 갈림길로 돌아와서 다른 방향으로 다시 탐색을 진행하는 방법과 유사

 

 

위와 같은 그림의 그래프 처럼 탐색을 하는 것이 DFS 탐색이라고 할 수 있다.  그러면 진행되는 과정을 자세히 한번 공부해보려 한다.

 

 

DFS 탐색은 어디에서 사용될까? 

미로 탐색에 사용된다. 

  • 미로 탐색시 한 방향으로 갈 수 있을 때까지 계속 탐색.

  • 모든 노드를 방문하고자 하는 경우에 사용

 

 

 

그래프에서 깊이 우선 탐색은 어떻게 진행될까?

  • 깊이 우선 탐색은 그래프의 시작 정점에서 출발하여 시작 정점 0을 방문하였다고 표시

  • 이어서 v에 인접한 정점들 중에서 아직 방문하지 않은 정점 1을 선택한다.

  • 그리고 만약 그러한 정점이 없다면 탐색은 종료한다. 

  • 만약 아직 방문하지 않은 정점이 남아 있다면 그 정점을 시작으로 하여 탐색을 다시 시작한다.

  • 깊이 우선 탐색도 자기 자신을 다시 호출하는 순환 알고리즘의 형태를 가지고 있다.

 

 

깊이 우선 탐색의 구현(인접 행렬)

깊이 우선 탐색을 구현하는 데는 2가지의 방법이 있다. 

  • 첫 번째 : 순환 호출을 이용

  • 두 번째 : 명시적인 스택을 이용 

 

이번에는 자바를 이용해서 순환 호출을 이용하는 방법으로 구현해보려고 한다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.util.LinkedList;
 
public class Graph {
    public int V;   //노드의 개수
    public LinkedList<Integer>[] adj;  //인접 리스트
    boolean[] visited;
 
    //생성자
    public Graph(int v){
        V = v;
        adj = new LinkedList[v];
        visited = new boolean[V];
 
        for(int i=0; i<v; i++){
            adj[i] = new LinkedList();
        }
    }
 
    void addEdge(int v, int w){
        adj[v].add(w);
    }
 
    void DFS(int v){   //순환 호출을 이용해서 구현
        visited[v] = true;
        System.out.print(v + " ");
 
        for(int k : adj[v]){
            if(!visited[k]){
                DFS(k);     //순환 호출
            }
        }
 
    }
}
 
 
 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  
package Data_Structure.DFS;
 
public class Test {
    public static void main(String[] args){
        Graph g = new Graph(4);
 
        g.addEdge(0,1);
        g.addEdge(0,2);
        g.addEdge(1,2);
        g.addEdge(2,0);
        g.addEdge(2,3);
        g.addEdge(3,3);
 
        g.DFS(2);
 
 
    }
}
 
 

 

위와 같이 순환호출을 이용해서 DFS를 구현하였다. 그리고 DFS 공부를 했는데 어느정도 어떤 탐색인지는 알겠지만 아직 응용은 안될 것 같다. 열심히 공부해야지 

 

 

 

깊이 우선 탐색의 분석

깊이 우선 탐색은 그래프의 모든 간선을 조사하므로 정점의 수가 n이고 간선의 수가 e인 그래프인 경우, 그래프가 인접 리스트로 표현되어 있다면 시간 복잡도가 O(n+e)이고, 인접 행렬로 표시되어 있다면 O(n*n)이다.

 

이는 희소 그래프인 경우 깊이 우선 탐색은 인접 리스트의 사용이 인접 행렬보다 시간적으로 유리함을 뜻한다. 

반응형