그래프
는 노드와 그 노드들을 연결하는 간선으로 구성된 자료구조다. 그래프는 여러 가지 방법으로 표현될 수 있고, 대표적으로 인접 행렬(Adjacency Matrix), 인접 리스트(Adjacency List), 간선 리스트(Edge List)가 있다.
그래프를 2차원 배열로 표현하는 방법
A[i][j] = 1
: 노드 𝑖에서 노드 j로 가는 간선이 존재함
𝐴[i][j] = 0
: 노드 i에서 노드 j로 가는 간선이 존재하지 않음
public static void main(String[] args) {
int V = 6; // 노드의 수 (0부터 6까지 총 7개의 노드)
int[] edge = {0, 1, 0, 2, 0, 5, 0, 6, 4, 3, 5, 3, 5, 4}; // 간선 정보
int[][] adjM = new int[V + 1][V + 1]; // 인접 행렬 초기화
// 간선 정보에 따라 인접 행렬 업데이트
for (int i = 0; i < edge.length / 2; i++) {
int n1 = edge[2 * i];
int n2 = edge[2 * i + 1];
adjM[n1][n2] = 1;
}
// 인접 행렬 출력
for (int[] row : adjM) {
System.out.println(Arrays.toString(row));
}
}
[0, 1, 1, 0, 0, 1, 1]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0]
[0, 0, 0, 0, 1, 0, 0]
public static void main(String[] args) {
int V = 6; // 노드의 수 (0부터 6까지 총 7개의 노드)
int[] edge = {0, 1, 0, 2, 0, 5, 0, 6, 3, 4, 3, 5, 4, 5, 4, 6}; // 간선 정보
int[][] adjM = new int[V + 1][V + 1]; // 인접 행렬 초기화
// 간선 정보에 따라 인접 행렬 업데이트 (무향 그래프)
for (int i = 0; i < edge.length / 2; i++) {
int n1 = edge[2 * i];
int n2 = edge[2 * i + 1];
adjM[n1][n2] = 1;
adjM[n2][n1] = 1; // 무향 그래프에서는 대칭 위치도 1로 설정
}
// 인접 행렬 출력
for (int[] row : adjM) {
System.out.println(Arrays.toString(row));
}
}
[0, 1, 1, 0, 0, 1, 1]
[1, 0, 0, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 1, 0]
[0, 0, 0, 1, 0, 1, 1]
[1, 0, 0, 1, 1, 0, 0]
[1, 0, 0, 0, 1, 0, 0]
각 노드에 연결된 노드들의 목록을 저장하는 방식
예를 들어, 노드 A에 연결된 노드가 B와 C라면, 인접 리스트는 다음과 같이 표현된다.
A : [B, C]
B : [A]
C : [A]
public static void main(String[] args) {
int V = 6; // 노드의 수 (0부터 6까지 총 7개의 노드)
int[] edge = {0, 1, 0, 2, 0, 5, 0, 6, 4, 3, 5, 3, 5, 4, 6, 4}; // 간선 정보
List<List<Integer>> adjL = new ArrayList<>(V + 1);
// 인접 리스트 초기화
for (int i = 0; i <= V; i++) {
adjL.add(new ArrayList<>());
}
// 간선 정보에 따라 인접 리스트 업데이트 (유향 그래프)
for (int i = 0; i < edge.length / 2; i++) {
int n1 = edge[2 * i];
int n2 = edge[2 * i + 1];
adjL.get(n1).add(n2);
}
// 인접 리스트 출력
for (int i = 0; i < adjL.size(); i++) {
System.out.println("Node " + i + ": " + adjL.get(i));
}
}
Node 0: [1, 2, 5, 6]
Node 1: []
Node 2: []
Node 3: []
Node 4: [3]
Node 5: [3, 4]
Node 6: [4]
public static void main(String[] args) {
int V = 6; // 노드의 수 (0부터 6까지 총 7개의 노드)
int[] edge = {0, 1, 0, 2, 0, 5, 0, 6, 4, 3, 5, 3, 5, 4, 6, 4}; // 간선 정보
List<List<Integer>> adjL = new ArrayList<>(V + 1);
// 인접 리스트 초기화
for (int i = 0; i <= V; i++) {
adjL.add(new ArrayList<>());
}
// 간선 정보에 따라 인접 리스트 업데이트 (무향 그래프)
for (int i = 0; i < edge.length / 2; i++) {
int n1 = edge[2 * i];
int n2 = edge[2 * i + 1];
adjL.get(n1).add(n2);
adjL.get(n2).add(n1); // 무향 그래프에서는 반대 방향도 추가
}
// 인접 리스트 출력
for (int i = 0; i < adjL.size(); i++) {
System.out.println("Node " + i + ": " + adjL.get(i));
}
}
Node 0: [1, 2, 5, 6]
Node 1: [0]
Node 2: [0]
Node 3: [4, 5]
Node 4: [3, 5, 6]
Node 5: [0, 3, 4]
Node 6: [0, 4]
인접 리스트와 인접 행렬을 모두 사용할 수 없는 경우에 간선 리스트를 사용한다.
간선 리스트는 각각의 간선을 시작 노드와 끝 노드의 쌍으로 표현한다.
간단한 리스트 형태:
각 간선을 두 개의 노드 쌍으로 표현하는 방법
예를 들어, 그래프에 (A-B), (B-C), (C-D)라는 간선이 있다면, 간선 리스트는 다음과 같다.
[[(A, B), (B, C), (C, D)]]
가중치 포함 리스트:
가중치가 있는 그래프의 경우, 간선 리스트는 노드 쌍과 함께 각 간선의 가중치를 포함할 수 있다.
예를 들어, (A-B) 간선의 가중치가 3, (B-C) 간선의 가중치가 5라면, 간선 리스트는 다음과 같이 표현될 수 있다.
[[(A, B, 3), (B, C, 5), (C, D, 2)]]
간선 리스트는 주로 그래프의 간선 집합을 다루는 알고리즘, 예를 들어 크루스칼(Kruskal) 알고리즘 같은 최소 스패닝 트리 알고리즘에서 자주 사용된다. 이러한 알고리즘에서는 간선의 가중치를 기준으로 간선들을 정렬하거나 선택하는 작업이 중요하기 때문에 간선 리스트 형태가 유리하다.
[graph] 그래프를 인접행렬 또는 인접리스트로 받아오기
[자료구조] 그래프를 저장하는 방법 3가지 : 인접 행렬, 인접 리스트, 간선 리스트 with Python