탐색 알고리즘 DFS/BFS

2021. 1. 24. 13:57
반응형

DFS (Depth-First-Search)

  • 깊이 우선 탐색 - 그래프에서 깊은 부분을 우선적으로 탐색하는 알고리즘
  • 그래프는 노드와 간선으로 표현되며 노드는 index로 표현하고 간선은 distance로 표현
  • 스택 자료구조를 이용

BFS(Breath-First-Search)

  • 너비 우선 탐색 - 그래프에서 가장 가까운 노드부터 우선적으로 탐색하는 알고리즘
  • 큐 자료구조를 이용

그래프는 다음 2가지 방식으로 표현 가능하다.

  • 인접 행렬 : 2차원 배열로 그래프의 관계를 표현
  • 인접 리스트 : 리스트로 그래프의 관계를 표현

 

인접 행렬 방식

    public static final int INF = (int)1e9;

    public static int[][] graph = new int[][]{
            {0,5,3},
            {5,0,INF},
            {3,INF,0}
    };
  • INF로 표현된 요소는 둘 사이가 연결되어있지 않다는 뜻이다.
  • 노드0은 노드1과 거리5만큼 떨어져 연결되어있다.
  • 노드1과 노드2는 연결되어있지 않다.
  • 노드0과 노드2는 거리3만큼 떨어져 연결되어있다.

인접 리스트 방식

public class Main {

    public static ArrayList<ArrayList<Node>> graph = new ArrayList<ArrayList<Node>>();

    public static void main(String[] args) {

        for(int i = 0; i < 3; i++){
            graph.add(new ArrayList<>());
        }

        graph.get(0).add(new Node(1,5));
        graph.get(0).add(new Node(2,3));

        graph.get(1).add(new Node(0,5));

        graph.get(2).add(new Node(0,3));
        
    }
}
  • 연결되어있지 않은 노드는 INF로 표현하지 않아도 된다.
  • 위 인접 행렬과 같은 노드와 거리로 표현된다.

인접 행렬, 인접 리스트 방식의 차이점

  • 인접행렬은 연결되어있지 않은 노드도 INF로 표현을 한다.
  • 인접 리스트는 연결되어있지 않으면 표현 자체를 하지 않는다.
  • 따라서 인접 리스트는 연결된 정보만을 표현하기 때문에 메모리를 인접행렬 방식보다 효율적으로 사용한다.
  • 하지만 인접 리스트 방식은 특정 두 노드가 연결되어 있는지에 대한 정보를 얻는 속도가 느리다.

DFS 동작 원리

  1. 탐색 시작 노드를 스택에 삽입하고 방문처리를 한다.
  2. 스택의 최상단 노드에 방문하지 않은 연결되어있는 인접 노드가 있으면 스택에 넣고 방문처리를 한다.
  3. 1,2번 과정을 반복한다.
public class Main {

    public static boolean[] visited = new boolean[100001];

    public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();

    public static void Dfs(int now){
        //스택에 시작노드를 넣고 방문처리
        visited[now] = true;
        System.out.println(" " + now);
        //시작노드와 연결된 노드부터 탐색
        for(int i = 0; i < graph.get(now).size(); i++){
            //인접 노드 중 방문하지 않은 노드가 있다면
            if(!visited[graph.get(now).get(i)]){
                Dfs(graph.get(now).get(i));
            }
        }

    }

    public static void main(String[] args) {
        //그래프 초기화
        for(int i = 0; i <= 9; i++){
            graph.add(new ArrayList<>());
        }

        //그래프 채워넣기
        graph.get(1).add(2);
        graph.get(1).add(3);
        graph.get(1).add(8);

        graph.get(2).add(1);
        graph.get(2).add(7);

        graph.get(3).add(1);
        graph.get(3).add(4);
        graph.get(3).add(5);

        graph.get(4).add(3);
        graph.get(4).add(5);

        graph.get(5).add(3);
        graph.get(5).add(4);

        graph.get(6).add(7);

        graph.get(7).add(2);
        graph.get(7).add(6);
        graph.get(7).add(8);

        graph.get(8).add(1);
        graph.get(8).add(7);

        Dfs(1);

    }
}

 

BFS 동작 원리

  1. 탐색 시작 노드를 큐에 삽입하고 방문처리
  2. 큐에서 노드를 꺼내 해당 노드에 인접하는 노드중 방문하지 않은 노드를 다 큐에 삽입하고 방문처리
  3. 2번 과정을 반복한다.
public class Main {

    public static boolean[] visited = new boolean[100001];

    public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();

    public static void Bfs(int now){
        Queue<Integer> queue = new LinkedList<>();
        //큐에 시작노드를 넣고 방문처리
        queue.offer(now);
        visited[now] = true;
        //큐가 빌때 까지 반복
        while(!queue.isEmpty()){
            //큐에서 노드를 꺼낸다.
            int node = queue.poll();
            System.out.print(" " + node);
            //인접한 노드중 방문하지 않은 노드 큐에 삽입
            for(int i = 0; i < graph.get(node).size(); i++){
                if(!visited[graph.get(node).get(i)]){
                    queue.offer(graph.get(node).get(i));
                    visited[graph.get(node).get(i)] = true;
                }
            }
        }

    }

    public static void main(String[] args) {
        //그래프 초기화
        for(int i = 0; i <= 9; i++){
            graph.add(new ArrayList<>());
        }

        //그래프 채워넣기
        graph.get(1).add(2);
        graph.get(1).add(3);
        graph.get(1).add(8);

        graph.get(2).add(1);
        graph.get(2).add(7);

        graph.get(3).add(1);
        graph.get(3).add(4);
        graph.get(3).add(5);

        graph.get(4).add(3);
        graph.get(4).add(5);

        graph.get(5).add(3);
        graph.get(5).add(4);

        graph.get(6).add(7);

        graph.get(7).add(2);
        graph.get(7).add(6);
        graph.get(7).add(8);

        graph.get(8).add(1);
        graph.get(8).add(7);

        Bfs(1);

    }
}
반응형

'자료구조와 알고리즘 > 알고리즘' 카테고리의 다른 글

신장 트리와 크루스칼 알고리즘  (0) 2022.02.06
서로소 집합 알고리즘  (0) 2022.02.06
이진 탐색  (0) 2021.02.02
정렬 알고리즘  (0) 2021.01.29

BELATED ARTICLES

more