Blog For Me

[자료구조와 알고리즘] 그래프 표현방법 본문

컴퓨터과학/자료구조&알고리즘

[자료구조와 알고리즘] 그래프 표현방법

PureStack 2021. 12. 16. 23:56

인접행렬 (Adjacency Matrix)

  • G=(V, E)는 정점의 수가 n인 그래프
  • 인접행렬: n x n인 2차원 배열
    • 행, 열 => 그래프의 정점
    • 간선 (Vi, Vj) ∈ E(G) => a[i][j] = 1 (인접한 경우)
    • 간선 (Vi, Vj) ∉ E(G) => a[i][j] = 0 (인접하지 않은 경우)
  • 무방향 그래프 : 어떤 정점 i의 차수는 그 행 또는 열의 합
  • 방향 그래프 : 행의 합은 진출차수, 열의 합은 진입차수

  • 정점 0의 인접 정점 : 1, 2
  • 정점 1의 인접 정점 : 0, 3
  • 정점 2의 인접 정점 : 0. 3
  • 정점 3의 인접 정점 : 1, 2

인접행렬 소스코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

class Graph {
    private int[][] adjGraph;

    public Graph(int size) { // 그래프 초기화
        this.adjGraph = new int[size][size];
    }

    public void insertDouble(int v1, int v2) { // 무방향 그래프 간선 추가
        adjGraph[v1][v2] = adjGraph[v2][v1] = 1;
    }

    public void insertSingle(int v1, int v2) { // 방향 그래프 간선 추가
        adjGraph[v1][v2] = 1;
    }

    public void printGraph() { // 그래프 출력
        for(int i=0;i<adjGraph.length;i++) {
            for(int j=0;j<adjGraph[i].length;j++) {
                System.out.print(adjGraph[i][j]+" ");
            }
            System.out.println();
        }
    }
}

public class GraphMatrix {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int size = 4;
        int edge = 4;

        Graph arr = new Graph(size);

        for(int i=0;i<edge;i++) {
            String str = br.readLine();
            StringTokenizer st = new StringTokenizer(str, " ");

            int v1 = Integer.parseInt(st.nextToken());
            int v2 = Integer.parseInt(st.nextToken());

            arr.insertDouble(v1, v2);

            // 방향 그래프일 경우에는 arr.insertSingle(v1, v2);
        }
        /*
         입력(무방향 그래프)

         0 1, 정점 0과 1 사이의 간선 추가
         0 2, 정점 0과 2 사이의 간선 추가
         1 3, 정점 1과 3 사이의 간선 추가
         2 3, 정점 2와 3 사이의 간선 추가

         */
        System.out.println();

        arr.printGraph();

        /*출력

           0 1 1 0
           1 0 0 1
           1 0 0 1
           0 1 1 0

        */

    }

}

 

  • 인접행렬의 수행 시간 : 최소 O(n2)
  • 인접행렬의 단점
    • n개의 정점을 가지는 그래프를 항상 n x n개의 메모리를 사용해야 한다.
    • 정점의 개수에 비해 간선의 개수가 적은 희소 그래프에 대한 인접 행렬은 희소 행렬이 되므로 메모리의 낭비 발생

인접 리스트 (Adjacency Lists)

  • 각 정점에 대한 인접 정점들을 연결하여 만든 단순 연결 리스트 -> 인접 행렬의 각 행을 연결 리스트로
  • 각 정점의 차수만큼 노드를 연결
    • 리스트 내의 노드들은 인접 정점에 대하여 오름차순으로 연결
  • 인접 리스트의 각 노드
    • 정점과 다음 인접 정점을 연결하는 링크 필드
  • 정점의 헤드 노드
    • 정점에 대한 리스트의 시작을 표현

  • n개의 정점, e개의 간선을 가진 무향 그래프의 인접 리스트
    • 헤드 노드 배열의 크기 : n
    • 연결하는 노드의 수 : 2e
    • 각 정점의 헤드에 연결된 노드의 수 : 정점의 차수
  • n개의 정점, e개의 간선을 가진 방향 그래프의 인접 리스트
    • 헤드 노드 배열의 크기 : n
    • 연결하는 노드의 수 : e
    • 각 정점의 헤드에 연결된 노드의 수 : 정점의 진출 차수
    • 역인접리스트 : 진입 차수
  • 위의 그림에서 정점 0에는 노드 2개가 있는데, 이는 정점 0의 차수는 2라는 의미이다.
  • 인접 리스트 소스 코드
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.StringTokenizer;

class Graph {
    private ArrayList<ArrayList<Integer>> listGraph;

    public Graph(int size) {
        this.listGraph = new ArrayList<ArrayList<Integer>>();

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

    public void insertDouble(int v1, int v2) {
        listGraph.get(v1).add(v2);
        listGraph.get(v2).add(v1);
    }

    public void insertSingle(int v1, int v2) {
        listGraph.get(v1).add(v2);
    }

    public void printGraph() {
        for(int i=0;i<listGraph.size()-1;i++) {
            System.out.print("Vertex "+i+" 인접리스트");
            for(int j=0;j<listGraph.get(i).size();j++) {
                System.out.print("-> " + listGraph.get(i).get(j));
            }
            System.out.println();
        }
    }
}

public class GraphList {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        Graph graph = new Graph(4); // 정점 4개 있는 그래프 생성
        int edge = 4; // 간선의 개수 4개

        for(int i=0;i<edge;i++) {
            String str = br.readLine();
            StringTokenizer st = new StringTokenizer(str, " ");

            int v1 = Integer.parseInt(st.nextToken());
            int v2 = Integer.parseInt(st.nextToken());

            graph.insertDouble(v1, v2);

            /*

             입력(무방향 그래프)

             0 1
             0 2
             1 3
             2 3

             */
        }

        graph.printGraph();
        /*
         출력

         Vertex 0 인접리스트-> 1-> 2
         Vertex 1 인접리스트-> 0-> 3
         Vertex 2 인접리스트-> 0-> 3
         Vertex 3 인접리스트-> 1-> 2

         */

    }

}

참고자료

 

https://freestrokes.tistory.com/87

 

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

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

freestrokes.tistory.com

 

https://wonit.tistory.com/238

 

[자료 구조] Java로 그래프 구현하기 :: 인접 리스트로 구현한 그래프

To Do 인접 리스트란? 가중치가 없는 그래프를 인접 리스트로 구현하기 가중치가 있는 그래프를 인접 리스트로 구현하기 지난 시간에 우리는 인접 행렬로 그래프를 그리는 시간을 가졌다. 오늘은

wonit.tistory.com

 

Comments