그래프는 연결되어 있는 원소간의 관계를 표현한 자료구조이다.
그래프는 노드(N, node)와 그 노드를 연결하는 간선(E, edge)의 집합으로 구성된다.
이러한 그래프를 저장하는 3가지가 있다.
인접 행렬이란, 그래프의 연결 관계를 행렬로 표현하여 이차원 배열로 나타내는 방식을 의미한다.
adj[i][j] : 노드 i에서 j로 가는 간선이 존재할 경우 1, 아니면 0
만약 표현하고자 하는 그래프가 방향이 없는 무향 그래프의 경우 노드 i에서 노드 j로 가는 길이 존재하면 노드 j에서 노드 i로 가는 길 또한 존재한다.
이러한 특성으로 인접 행렬을 구현할 경우, 대각 성분을 기준으로 대칭인 성질을 가지게 된다.
👇 인접 행렬의 가중치가 있는 방향 그래프
👇 인접 행렬의 가중치가 없는 무방향 그래프
💻 인접 행렬 (방향 그래프) 구현
V, E = 6, 8
edge = [0, 1, 0, 2, 0, 5, 0, 6, 4, 3, 5, 3, 5, 4, 6, 4]
adj_matrix = [[0]*(V+1) for _ in range(V+1)]
for i in range(E):
# 2*i와 2*i+1은 edge 리스트에서 간선 정보를 가져오기 위한 인덱스
num1, num2 = edge[2*i], edge[2*i+1]
# num1 정점에서 num2 정점으로의 방향성을 가진 간선이 존재함을 나타냄
adj_matrix[num1][num2] = 1
💻 인접 행렬 (무방향 그래프) 구현
V, E = 6, 8
edge = [0, 1, 0, 2, 0, 5, 0, 6, 4, 3, 5, 3, 5, 4, 6, 4]
adj_matrix = [[0]*(V+1) for _ in range(V+1)]
for i in range(E):
# 2*i와 2*i+1은 edge 리스트에서 간선 정보를 가져오기 위한 인덱스
num1, num2 = edge[2*i], edge[2*i+1]
# 각 인덱스에 1을 할당하여 num1과 num2 사이에 간선의 존재 여부를 나타냄
adj_matrix[num1][num2] = 1
adj_matrix[num2][num1] = 1
🟢 인접 행렬의 장점
🔴 인접 행렬의 단점
인접 리스트란, 각각의 노드에 연결된 노드들을 원소로 갖는 리스트들의 배열을 의미한다.
adj[i] : i번째 노드에 연결된 노드들을 원소로 갖는 리스트
인접 리스트 또한 무방향 그래프의 경우에는 본인 노드 인덱스의 리스트 내에 서로를 원소로 가지게 된다.
👇 인접 리스트의 가중치가 있는 방향 그래프
👇 인접 리스트의 가중치가 없는 무방향 그래프
💻 인접 리스트 (방향 그래프) 구현
V, E = 6, 8
edge = [0, 1, 0, 2, 0, 5, 0, 6, 4, 3, 5, 3, 5, 4, 6, 4]
# 인접 리스트를 생성하여 각 정점에 연결된 간선 정보를 저장할 배열
adj_list = [[] for _ in range(V+1)]
for i in range(E):
# 현재 간선을 구성하는 시작 정점과 끝 정점을 num1, num2 변수에 할당
# 2*i와 2*i+1은 edge 리스트에서 간선 정보를 가져오기 위한 인덱스
num1, num2 = edge[2*i], edge[2*i+1]
# num1 정점에 연결된 간선의 끝 정점 num2를 adj_list 리스트에 추가
# num1 정점과 num2 정점이 방향성을 가진 간선으로 연결되어 있다는 정보를 인접 리스트에 저장
adj_list[num1].append(num2)
💻 인접 리스트 (무방향 그래프) 구현
V, E = 6, 8
edge = [0, 1, 0, 2, 0, 5, 0, 6, 4, 3, 5, 3, 5, 4, 6, 4]
# 인접 리스트를 생성하여 각 정점에 연결된 간선 정보를 저장할 배열
adj_list = [[] for _ in range(V+1)]
for i in range(E):
# 현재 간선을 구성하는 시작 정점과 끝 정점을 num1, num2 변수에 할당
# 이때 2*i와 2*i+1은 edge 리스트에서 간선 정보를 가져오기 위한 인덱스
num1, num2 = edge[2*i], edge[2*i+1]
# num1 정점에 연결된 간선의 끝 정점 num2를 adj_list에 추가
# 이것은 num1 정점과 num2 정점이 연결되어 있다는 정보를 인접 리스트에 저장하는 것을 의미
adj_list[num1].append(num2)
# 무방향 그래프이기 때문에 num2 정점에도 num1 정점을 연결된 간선의 끝 정점으로 추가
# 이것은 num2 정점과 num1 정점이 연결되어 있다는 정보를 인접 리스트에 저장하는 것을 의미
adj_list[num2].append(num1)
🟢 인접 리스트의 장점
🔴 인접 리스트의 단점
간선 리스트는 인접 리스트와 인접 행렬을 모두 사용할 수 없는 경우에 간선 리스트를 사용한다.
STL, Array, collection 등을 사용할 수 없는 경우에 해당된다.
하나의 배열을 이용하여 모든 간선은 저장하고, 누적합을 저장한 다른 배열로 한 정점의 간선이 저장된 index의 범위를 알려주도록 한다.
👇 간선 리스트의 그래프
💻 간선 리스트 (방향 그래프) 구현
V = 7
edge = [(1, 2), (1, 5), (2, 1), (2, 3), (2, 4), (2, 5), (3, 2), (3, 4), (3, 4), (4, 2), (4, 3), (4, 5), (4, 6), (5, 1), (5, 2), (5, 4), (6, 4)]
agj_list = [[] for _ in range(V)]
for u, v in edge:
# 시작 정점 u와 끝 정점 v를 추출하여 adj_list에 각각의 정점을 연결
# 방향 그래프이므로 u 정점에 v를 추가
adj_list[u].append(v)
💻 간선 리스트 (무방향 그래프) 구현
V = 7
edge = [(1, 2), (1, 5), (2, 1), (2, 3), (2, 4), (2, 5), (3, 2), (3, 4), (3, 4), (4, 2), (4, 3), (4, 5), (4, 6), (5, 1), (5, 2), (5, 4), (6, 4)]
agj_list = [[] for _ in range(V)]
for u, v in edge:
# 시작 정점 u와 끝 정점 v를 추출하여 adj_list에 각각의 정점을 연결
# 무방향 그래프이므로 u 정점에 v를, v 정점에 u를 추가
adj_list[u].append(v)
adj_list[v].append(u)
🟢 간선 리스트의 장점
🔴 간선 리스트의 단점
(책) 프로그래밍 대회에서 배우는 알고리즘 문제해결전략
https://ninefloor-design.tistory.com/165
https://livecoding.tistory.com/49
https://ko.wikipedia.org/wiki/%EC%9D%B8%EC%A0%91%ED%96%89%EB%A0%AC
https://ko.wikipedia.org/wiki/%EC%9D%B8%EC%A0%91_%EB%A6%AC%EC%8A%A4%ED%8A%B8