코딩테스트/알고리즘 정리

인접 행렬과 인접 리스트

까루카라 2024. 3. 20. 18:32

그래프를 구현하여 표현하는 방법에는 여러가지가 있지만 일반적으로 인접행렬과 인접리스트 방식이 있다. 

이 두가지 방식은 서로 정반대의 특징을 갖기 때문에 한 방식의 장점이 다른 방식의 단점이 되는 경우가 나타난다. 

따라서, 구현하려는 알고리즘, 그래프의 종류에 따라 적절하게 사용하여야 한다. 

 

인접 리스트를 이용한 그래프 구현

package boj.study.week6;

import java.util.ArrayList;

public class adjacencyList {
    public static void main(String[] args) {
        int initSize = 6;
        ListGraph adjList = new ListGraph(initSize);

        adjList.put(1, 2);
        adjList.put(1, 3);
        adjList.put(2, 3);
        adjList.put(2, 4);
        adjList.put(3, 4);
        adjList.put(3, 5);
        adjList.put(4, 5);
        adjList.put(4, 6);

        adjList.printGraphToAdjList();

    }
}

// 그래프(리스트) 클래스
class ListGraph {
    private ArrayList<ArrayList<Integer>> listGraph;

    // 생성자
    public ListGraph(int initSize) {
        this.listGraph = new ArrayList<ArrayList<Integer>>();

        /**
         * 그래프 초기화
         * put(int x, int y) 에서 입력되는 정점의 값은 0 이상의 정수이나
         * ArrayList의 index는 0 부터 시작이므로
         * ArrayIndexOutOfBoundsException을 방지하기 위해
         * 정점을 담는 인접리스트의 size는 1을 더하여 초기화해줌
         * ex) initSize = 3
         * graph[0] -> 2 -> 3
         * graph[1] -> 1 -> 3 -> 4
         * graph[2] -> 1 -> 2 -> 4 -> 5
         * graph[3] -> 1 -> 2 -> 4 -> 5
         */
        for (int i = 0; i < initSize + 1; i++) {
            listGraph.add(new ArrayList<Integer>());
        }
    }

    public ArrayList<ArrayList<Integer>> getGraph() {
        return this.listGraph;
    }

    // 그래프 추가 (양방향)
    public void put(int x, int y) {
        listGraph.get(x).add(y);
        listGraph.get(y).add(x);
    }

    // 그래프 추가 (단방향)
    public void putSingle(int x, int y) {
        listGraph.get(x).add(y);
    }

    // 그래프 출력 (인접 리스트)
    public void printGraphToAdjList() {
        for (int i = 1; i < listGraph.size(); i++) {
            System.out.print("정점 " + i + "의 인접리스트");

            for (int j = 0; j < listGraph.get(i).size(); j++) {
                System.out.print(" -> " + listGraph.get(i).get(j));
            }
            System.out.println();
        }
    }
}

실행 결과

 

 

인접 행렬을 이용한 그래프 구현

인접 행렬은 N x N 행렬로 graph[i][j]가 true라면 i에서 j로의 간선이 있다는 것을 의미

정점의 개수가 V라면 V^2 크기의 2차원 배열을 생성하여 1과 0을 사용하여 true / false를 구분하여 값을 저장한다. 

양방향 인접행렬의 경우 대칭 행렬의 형태로 구성된다. 

 

package boj.study.week6;

public class adjacencyArray {
    public static void main(String[] args) {
        int initSize = 6;
        ArrGraph adjArr = new ArrGraph(initSize);

        adjArr.put(1, 2);
        adjArr.put(1, 3);
        adjArr.put(2, 3);
        adjArr.put(2, 4);
        adjArr.put(3, 4);
        adjArr.put(3, 5);
        adjArr.put(4, 5);
        adjArr.put(4, 6);
        
        adjArr.printGraphToAdjArr();
    }
}

class ArrGraph {
    private int[][] arrGraph;

    public ArrGraph(int initSize) {
        /**
         * 그래프 초기화
         * put(int x, int y)에서 입력되는 정점의 값은 0 이상의 정수이나
         * 배열의 indexsms 0 부터 시작이므로
         * ArrayIndexOutOfBoundsException을 방지하기 위해
         * 정점을 담는 인접행렬의 행과 열 size는 1을 더하여 초기화 해줌
         */
        this.arrGraph = new int[initSize + 1][initSize + 1];
    }

    // 그래프 return
    public int[][] getGraph() {
        return this.arrGraph;
    }

    // 그래프 추가(양방향)
    public void put(int x, int y) {
        this.arrGraph[x][y] = this.arrGraph[y][x] = 1;
    }

    // 그래프 추가(단방향)
    public void putSingle(int x, int y) {
        this.arrGraph[x][y] = 1;
    }

    // 그래프 출력 (인접행렬)
    public void printGraphToAdjArr() {
        for (int i = 1; i < arrGraph.length; i++) {
            for (int j = 1; j < arrGraph[i].length; j++) {
                System.out.print(" " + arrGraph[i][j]);
            }
            System.out.println();
        }
    }
}

 

실행 결과

 

인접 행렬과 인접 리스트의 차이

  정점 간의 간선 여부 공간 복잡도
인접 행렬 정점 v1, v2에 대해 한 번의 접근으로 확인 가능 V개의 노드 표현을 위해 V^2 만큼의 공간이 필요
인접 노드를 찾기 위해선 모든 노드를 순회해야 함 
공간복잡도 : O(V^2)
인접 리스트 리스트의 처음부터 하나씩 확인해야 함 V 개의 리스트에 간선 (E) 만큼 원소가 들어있음
인접 노드를 쉽게 찾을 수 있음
공간복잡도 : O(V + E)

 

인접 행렬과 인접 리스트가 사용되는 경우

인접 행렬 : 그래프에 간선이 많이 존재하는 밀집 그래프

인접 리스트 : 그래프에 간선이 적게 존재하는 희소 그래프

 

 

 

 

https://freestrokes.tistory.com/87

 

Java 인접행렬과 인접리스트를 이용하여 그래프 구현하기

Java 인접행렬과 인접리스트를 이용하여 그래프 구현하기 Java로 인접행렬과 인접리스트를 만들어 그래프를 구현하는 방법에 대해 알아보겠습니다. 1. 그래프 (Graph) 수학적 정의로 그래프는 객체

freestrokes.tistory.com