본문 바로가기
알고리즘 이전/재귀, DFS, BFS, Tree, Graph

경로 탐색(DFS, 인접리스트, ArrayList)

by hoshi03 2023. 8. 17.

위 그림같은 방향 그래프를 1번부터 시작해서 5번까지 가는 방법의 갯수를 구해보자

 

인접행렬은 for문, 인접리스트는 foreach문을 사용, 인접리스트 처음에 생성할때 i = 0; i <= m ; i++

 

 

인접 행렬

 

방문한 노드를 체크할 배열과, 한 노드가 방문할수 있는 다른 노드들을 체크할 2차원 배열을 만들고 방문 가능한 노드들을 채워준다  

        for (int i = 0; i < m; i++){
            int a = in.nextInt();
            int b = in.nextInt();
            graph[a][b]= 1;
        }

dfs 함수에서는 노드 길이만큼 for문을 돌면서 현재 정점에서 방문 가능한 노드이고 간 적이 없으면 그 노드를 방문한다

목적지 노드까지 도달하면 갯수를 늘려준다, 한 노드를 방문할땐 방문여부를 체크하고 다시 뒤로 돌아올땐 체크를 푼다.

public int dfs(int v){
        if (v == n) ans++;

        else {
            for (int i = 1; i <= n; i++){
                //현재 정점에서 for문으로 n번 노드중 갈 수 있는 노드 찾기
                if(graph[v][i] == 1 && ch[i] == 0){
                    ch[i] = 1;
                    dfs(i);
                    ch[i] = 0;
                }
            }
        }
        return ans;
    }

 

인접행렬 경로탐색 전체 코드

 

import java.util.*;


public class Main{
    static int n,m,ans = 0;
    static int[][] graph;
    static int[] ch;

    public int dfs(int v){
        if (v == n) ans++;

        else {
            for (int i = 1; i <= n; i++){
                //현재 정점에서 for문으로 n번 노드중 갈 수 있는 노드 찾기
                if(graph[v][i] == 1 && ch[i] == 0){
                    ch[i] = 1;
                    dfs(i);
                    ch[i] = 0;
                }
            }
        }
        return ans;
    }

    public static void main(String args[]) {
        Main T = new Main();
        Scanner in = new Scanner(System.in);

        n = in.nextInt();
        m = in.nextInt();
        graph = new int[n+1][n+1];
        ch = new int[n+1];

        //그래프의 a -> b 방향으로 방문 가능한 곳을 채워둠
        for (int i = 0; i < m; i++){
            int a = in.nextInt();
            int b = in.nextInt();
            graph[a][b]= 1;
        }

        ch[1] = 1;
        System.out.print(T.dfs(1));
    }
}

 

ArrayList로 경로 탐색

 

인접행렬로는 n이 커지면 너무 비효율적이다

1~n을 가지는 배열리스트를 만들고해당 정점에서 갈 수 있는 노드를 리스트에 추가, 탐색한다

1 | 2, 3, 4

2 | 1, 3, 5

3 | 4

4 | 2, 5

 

위 형태로 ArrayList 안에 각 노드 번호의 ArrayList를 만들고 각 노드에서 한번만에 갈 수 있는 노드들을

추가해준다, 이걸 위해서 ArrayList안에 ArrayList를 가진 형태로 그래프를 만들어준다

 

static ArrayList<ArrayList<Integer>>graph;
arraylist를 가지는 arraylist 객체

get으로 ArrayList의 인덱스를 가져올때 0번부터 시작하므로 0번부터 n번까지 진행해서 앞에 한칸을 추가해 인덱스를 맞춰준다

// 정점개수 n 만큼 그래프에 배열리스트 추가
// 중요! 0부터 n까지 하는 이유는 get으로 인덱스를 조회할때 0번부터 시작하기 때문에 
// 앞에 한칸을 더 해줘야 인덱스에 딱 맞게 추가 가능하다
for(int i = 0; i <=n; i++) {
	graph.add(new ArrayList<Integer>());
}

위의 그린 그림대로 방문 가능한 정점을 추가한다

        for (int i = 0; i < m; i++){
            int a = in.nextInt();
            int b = in.nextInt();
            //위에 만든 인덱스에 맞는 배열 리스트에 방문 가능한 정점을 추가
            graph.get(a).add(b);
        }

인접 리스트 DFS 함수는 foreach문으로 해당 인덱스 노드에서 갈수 있는 노드를 순회한다

public void dfs(int v){
        if (v == n) ans++;
        else {
            //현재 정점에서 foreach문으로 n번 노드중 갈 수 있는 노드 찾기
            for (int nv : graph.get(v)){
                if(ch[nv] == 0){
                    ch[nv] = 1;
                    dfs(nv);
                    ch[nv] = 0;
                }
            }
        }
    }

인접 리스트 경로 탐색 전체 코드 

import java.util.*;


public class Main{
    static int n,m,ans = 0;
    static ArrayList<ArrayList<Integer>> graph;
    static int[] ch;

    public void dfs(int v){
        if (v == n) ans++;
        else {
            //현재 정점에서 foreach문으로 n번 노드중 갈 수 있는 노드 찾기
            for (int nv : graph.get(v)){
                if(ch[nv] == 0){
                    ch[nv] = 1;
                    dfs(nv);
                    ch[nv] = 0;
                }
            }
        }
    }

    public static void main(String args[]) {
        Main T = new Main();
        Scanner in = new Scanner(System.in);

        n = in.nextInt();
        m = in.nextInt();
        graph = new ArrayList<ArrayList<Integer>>();

        // 정점개수 n 만큼 그래프에 배열리스트 추가
        //  중요! 0부터 n까지 하는 이유는 get으로 인덱스를 조회할때 0번부터 시작하기 때문에 앞에 한칸을 더 해줘야 인덱스에 딱 맞게 추가 가능하다
        for(int i = 0; i <=n; i++) {
            graph.add(new ArrayList<Integer>());
        }
        ch = new int[n+1];
        for (int i = 0; i < m; i++){
            int a = in.nextInt();
            int b = in.nextInt();
            //위에 만든 인덱스에 맞는 배열 리스트에 방문 가능한 정점을 추가
            graph.get(a).add(b);
        }

        ch[1] = 1;
        T.dfs(1);
        System.out.println(ans);
    }
}

'알고리즘 이전 > 재귀, DFS, BFS, Tree, Graph' 카테고리의 다른 글

합이 같은 부분집합  (0) 2023.08.23
그래프 최단거리(BFS)  (0) 2023.08.18
말단 노드까지의 가장 짧은 경로  (0) 2023.08.16
송아지 찾기(BFS)  (0) 2023.08.15
레벨 탐색(BFS)  (0) 2023.08.15