그래프 (자료 구조)
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
그래프(자료 구조)는 그래프를 표현하기 위한 다양한 자료 구조를 설명하는 문서이다. 주요 자료 구조로는 정점과 인접한 정점의 리스트를 저장하는 인접 리스트, 2차원 행렬로 표현되는 인접 행렬, 그리고 정점과 간선의 관계를 나타내는 사고 행렬이 있다. 그래프의 표현 방식은 그래프의 크기와 문제의 특성에 따라 선택되며, 인접 리스트는 희소 그래프에, 인접 행렬은 조밀 그래프에 적합하다. 그래프 자료 구조는 인접 여부 확인, 인접 정점 나열, 정점 및 간선 추가/제거 등의 연산을 제공하며, 최단 경로 문제 해결을 위한 다익스트라 알고리즘, 최대 유량 문제 해결을 위한 포드-풀커슨 알고리즘 등 다양한 알고리즘에 활용된다. 병렬 환경에서의 그래프 표현은 공유 메모리 모델과 분산 메모리 모델에 따라 다르며, 대규모 그래프를 효율적으로 처리하기 위한 압축된 그래프 표현도 존재한다.
그래프를 실제로 표현하기 위한 자료 구조는 여러 종류가 있으며, 문제의 특성과 그래프의 크기에 따라 적절한 자료 구조를 선택해야 한다. 그래프를 표현하는 자료 구조는 크게 리스트를 이용한 방식과 행렬을 이용한 방식으로 나눌 수 있다.
2. 그래프 자료 구조
각 표현 방식에 따른 그래프 연산의 시간 복잡도는 다음 표와 같다. 여기서 |''V''|는 정점의 수, |''E''|는 간선의 수를 의미한다.
| 인접 리스트 | 인접 행렬 | 발생 행렬 | |
|---|---|---|---|
| 그래프 저장 | O(>V|+|E|) | O(>V|^2) | O(>V|\cdot|E|) |
| 정점 추가 | O(>V|^2) | O(>V|\cdot|E|) | |
| 간선 추가 | O(>V|\cdot|E|) | ||
| 정점 제거 | O(>E|) | O(>V|^2) | O(>V|\cdot|E|) |
| 간선 제거 | O(>V|) | O(>V|\cdot|E|) | |
| 정점 x와 y가 인접한가? | O(>V|) | O(>E|) | |
| 비고 | 정점 또는 간선을 모두 찾아야 하므로 정점과 간선을 제거하는 속도가 느림 | 행렬의 크기를 조정/복사해야 하므로 정점을 추가하거나 제거하는 속도가 느림 | 행렬의 크기를 조정/복사해야 하므로 정점과 간선을 추가하거나 제거하는 속도가 느림 |
일반적으로 희소 그래프는 인접 리스트로 표현하는 것이 효율적이며, 조밀 그래프는 인접 행렬이 더 효율적이다.[5][6]
2. 1. 리스트 자료 구조
리스트를 이용하여 그래프를 표현하는 방식은 다음과 같다.- 발생 리스트(Incidence list): 변으로 연결된 두 꼭짓점 (방향이 있다면 순서가 존재함)과 가중치 등의 데이터를 배열로 표현한다.[1] 이때 변으로 연결된 두 꼭짓점은 서로 ''인접''한 관계라고 한다.[1]
- 인접 리스트(Adjacency list): 각 꼭짓점에 인접한 꼭짓점들의 리스트를 가진다.
2. 1. 1. 인접 리스트 (Adjacency list)
인접 리스트는 각 꼭짓점에 인접한 꼭짓점들의 리스트를 저장하는 방식이다. 방향성이 없는 그래프에서는 A와 B가 인접하면 A의 인접 리스트에 B가 포함되고, B의 인접 리스트에도 A가 포함되는 불필요한 정보가 생긴다. 이처럼 추가적인 저장 공간이 필요하지만, 인접 정보를 빠르게 얻을 수 있다.[2]정점은 레코드나 객체로 저장되며, 각 정점은 인접한 정점의 리스트를 저장한다. 이 구조를 사용하면 정점에 추가 데이터를 저장할 수 있다. 간선도 객체로 저장하는 경우, 각 정점은 연결된 간선을, 각 간선은 연결된 정점을 저장하여 추가 데이터를 저장할 수 있다.[2]
인접 리스트는 희소 그래프 표현에 주로 사용된다.[5][6]
다음 표는 그래프에서 다양한 연산을 수행하는 데 드는 시간 복잡도를 나타낸다. 여기서 |''V''|는 정점의 수, |''E''|는 간선의 수이다.
| 인접 리스트 | |
|---|---|
| 그래프 저장 | O(>V|+|E|) |
| 정점 추가 | |
| 간선 추가 | |
| 정점 제거 | O(>E|) |
| 간선 제거 | O(>V|) |
| 정점 x와 y가 인접한가? (저장 위치가 알려져 있다고 가정) | O(>V|) |
| 비고 | 정점 또는 간선을 모두 찾아야 하므로 정점과 간선 제거 속도가 느림 |
해시 테이블이나 균형 이진 탐색 트리와 같은 효율적인 자료 구조에 인접 정점 집합을 저장하면 인접 리스트 표현에서의 연산 시간 복잡도를 개선할 수 있다.[7]
2. 1. 2. 발생 리스트 (Incidence list)
변은 변으로 연결된 두 꼭짓점(방향이 있다면 순서가 존재함)과 가중치, 다른 특정 데이터들을 포함하는 배열로 표현된다.[1] 변으로 연결된 두 꼭짓점은 서로 ''인접''한 관계라고 일컫는다.[1]2. 2. 행렬 자료 구조
행렬을 이용하여 그래프를 표현하는 방식에는 발생 행렬(Incidence matrix)과 인접 행렬이 있다.발생 행렬(Incidence matrix)은 그래프의 변을 열로, 꼭짓점을 행으로 하는 행렬로 표현한다. 행렬[꼭짓점, 변]은 변의 끝점에 대한 데이터를 가지며, 가장 간단한 경우 1은 연결됨, 0은 연결되지 않음을 의미한다. 행렬의 크기는 |V|·|E| (꼭짓점의 수 × 변의 수)로 나타낸다.[4]
| 인접 리스트 | 인접 행렬 | 발생 행렬(Incidence matrix) | |
|---|---|---|---|
| 그래프 저장 | O(>V|+|E|) | O(>V|^2) | O(>V|\cdot|E|) |
| 정점 추가 | O(>V|^2) | O(>V|\cdot|E|) | |
| 간선 추가 | O(>V|\cdot|E|) | ||
| 정점 제거 | O(>E|) | O(>V|^2) | O(>V|\cdot|E|) |
| 간선 제거 | O(>V|) | O(>V|\cdot|E|) | |
| 정점 x와 y가 인접한가? | O(>V|) | O(>E|) | |
| 비고 | 정점 또는 간선을 모두 찾아야 하므로 정점과 간선을 제거하는 속도가 느림 | 행렬의 크기를 조정/복사해야 하므로 정점을 추가하거나 제거하는 속도가 느림 | 행렬의 크기를 조정/복사해야 하므로 정점과 간선을 추가하거나 제거하는 속도가 느림 |
2. 2. 1. 인접 행렬 (Adjacency matrix)
인접 행렬은 그래프를 표현하는 방법 중 하나로, 2차원 배열을 사용한다. 행렬의 크기는 |V| × |V| (꼭짓점의 수)이다.[3] 행은 출발 정점을, 열은 도착 정점을 나타내며, 꼭짓점 x에서 꼭짓점 y로 변이 존재하면 행렬의 x행 y열 값은 1이고, 그렇지 않으면 0이다.[2] 간선 및 정점에 대한 데이터는 외부에 저장해야 하며, 각 정점 쌍 사이에 하나의 간선에 대한 비용만 저장할 수 있다.[3]인접 행렬은 부분 그래프(subgraph)나 역(reverse) 그래프를 쉽게 찾을 수 있게 해준다.[2] 조밀 그래프(Dense graph)처럼 간선의 수가 정점의 제곱에 가까운 경우, 또는 두 정점을 연결하는 간선이 있는지 빠르게 확인해야 하는 경우에 인접 행렬이 선호된다.[5][6]
| 인접 리스트 | 인접 행렬 | 발생 행렬(Incidence matrix) | |
|---|---|---|---|
| 그래프 저장 | O(>V|+|E|) | O(>V|^2) | O(>V|\cdot|E|) |
| 정점 추가 | O(>V|^2) | O(>V|\cdot|E|) | |
| 간선 추가 | O(>V|\cdot|E|) | ||
| 정점 제거 | O(>E|) | O(>V|^2) | O(>V|\cdot|E|) |
| 간선 제거 | O(>V|) | O(>V|\cdot|E|) | |
| 정점 x와 y가 인접한가? | O(>V|) | O(>E|) | |
| 비고 | 정점 또는 간선을 모두 찾아야 하므로 정점과 간선을 제거하는 속도가 느림 | 행렬의 크기를 조정/복사해야 하므로 정점을 추가하거나 제거하는 속도가 느림 | 행렬의 크기를 조정/복사해야 하므로 정점과 간선을 추가하거나 제거하는 속도가 느림 |
2. 2. 2. 발생 행렬 (Incidence matrix)
발생 행렬(Incidence matrix)은 그래프에서 변을 열로, 꼭짓점을 행으로 하는 행렬로 표현되며, 행렬[꼭짓점, 변]은 변의 끝점에 대한 데이터를 가진다(가장 간단한 경우: 1은 연결됨을 의미, 0은 연결되지 않음을 의미). 행렬의 크기는 |V|·|E| (꼭짓점의 수 × 변의 수)로 나타낸다.3. 그래프 표현의 선택
그래프의 크기, 밀도, 그리고 수행할 연산의 종류에 따라 적절한 표현 방식을 선택해야 한다. 희소 그래프는 인접 리스트가, 조밀 그래프는 인접 행렬이 일반적으로 효율적이다. 알고리즘의 요구 사항에 따라 추가적인 데이터를 저장해야 하는 경우도 있다.[5][6]
- 인접 리스트: 정점은 레코드 또는 객체로 저장되며, 각 정점은 인접한 정점의 리스트를 저장한다. 이 데이터 구조를 사용하면 정점에 대한 추가 데이터를 저장할 수 있다. 간선도 객체로 저장하는 경우, 각 정점은 연결된 간선을 저장하고 각 간선은 연결된 정점을 저장하므로 추가 데이터를 저장할 수 있다.[2]
- 인접 행렬: 2차원 행렬로, 행은 출발 정점을 나타내고 열은 도착 정점을 나타낸다. 간선 및 정점에 대한 데이터는 외부에 저장해야 한다. 각 정점 쌍 사이에 하나의 간선에 대한 비용만 저장할 수 있다.[3]
- 사고 행렬: 2차원 행렬로, 행은 정점을 나타내고 열은 간선을 나타낸다. 항목은 행의 정점과 열의 간선 사이의 사고 관계를 나타낸다.[4]
다음 표는 각 표현에 대해 그래프에서 다양한 연산을 수행하는 데 드는 시간 복잡도 비용을 나타낸다. 여기서 |''V''|는 정점의 수이고 |''E''|는 간선의 수이다. 행렬 표현에서 항목은 간선을 따르는 비용을 인코딩한다. 존재하지 않는 간선의 비용은 ∞로 가정한다.
| 인접 리스트 | 인접 행렬 | 사고 행렬 | |
|---|---|---|---|
| 그래프 저장 | O(>V|+|E|) | O(>V|^2) | O(>V|\cdot|E|) |
| 정점 추가 | O(>V|^2) | O(>V|\cdot|E|) | |
| 간선 추가 | O(>V|\cdot|E|) | ||
| 정점 제거 | O(>E|) | O(>V|^2) | O(>V|\cdot|E|) |
| 간선 제거 | O(>V|) | O(>V|\cdot|E|) | |
| 정점 x와 y가 인접한가 (저장 위치가 알려져 있다고 가정)? | O(>V|) | O(>E|) | |
| 비고 | 정점 또는 간선을 모두 찾아야 하므로 정점과 간선을 제거하는 속도가 느림 | 행렬의 크기를 조정/복사해야 하므로 정점을 추가하거나 제거하는 속도가 느림 | 행렬의 크기를 조정/복사해야 하므로 정점과 간선을 추가하거나 제거하는 속도가 느림 |
일반적으로 희소 그래프는 인접 리스트로 표현하는 것이 좋고, 그래프가 조밀하여 간선 의 수가 정점의 제곱 에 가깝거나, 두 정점을 연결하는 간선이 있는지 빠르게 찾아야 하는 경우에는 인접 행렬이 선호된다. 매우 큰 그래프에서 간선에 어떠한 규칙성이 있는 경우, 심볼릭 그래프라는 표현도 고려할 수 있다.
4. 그래프 연산
그래프 자료 구조는 다양한 연산을 제공하며, 이러한 연산은 그래프 알고리즘의 기본 구성 요소가 된다. 그래프 연산에는 기본적인 정점 및 간선 관리, 그래프 탐색, 최단 경로 문제 해결, 최대 유량 문제 해결 등이 포함된다.
4. 1. 기본 연산
그래프 자료 구조 ''G''가 제공하는 기본적인 연산은 일반적으로 다음과 같다:[1]- adjacent(''G'', ''x'', ''y''): 정점 ''x''에서 정점 ''y''로의 간선이 있는지 확인한다.
- neighbors(''G'', ''x''): 정점 ''x''에 인접한 모든 정점 ''y''를 나열한다.
- add_vertex(''G'', ''x''): 정점 ''x''를 추가한다.
- remove_vertex(''G'', ''x''): 정점 ''x''를 제거한다.
- add_edge(''G'', ''x'', ''y'', ''z''): 정점 ''x''에서 정점 ''y''로의 간선 ''z''를 추가한다.
- remove_edge(''G'', ''x'', ''y''): 정점 ''x''에서 정점 ''y''로의 간선을 제거한다.
- get_vertex_value(''G'', ''x''): 정점 ''x''와 연관된 값을 반환한다.
- set_vertex_value(''G'', ''x'', ''v''): 정점 ''x''와 연관된 값을 ''v''로 설정한다.
간선에 값을 연관시키는 구조는 일반적으로 다음도 제공한다:[1]
- get_edge_value(''G'', ''x'', ''y''): 간선 (''x'', ''y'')와 연관된 값을 반환한다.
- set_edge_value(''G'', ''x'', ''y'', ''v''): 간선 (''x'', ''y'')와 연관된 값을 ''v''로 설정한다.
4. 2. 그래프 탐색
그래프 탐색은 그래프의 모든 꼭짓점을 방문하는 과정이다. 그래프 관련 알고리즘은 매우 많으며, 널리 연구되고 있다. 그래프 관련 전형적인 작업으로는 두 노드 간의 경로를 찾는 것이 있다. 깊이 우선 탐색이나 너비 우선 탐색 같은 기법을 사용하여 어떤 노드에서 다른 노드로 가는 최단 경로를 구할 수 있다. 다익스트라 알고리즘이 그 예시이다. 모든 노드 조합에 대해 각각의 최단 경로를 구하는 플로이드-워셜 알고리즘도 있다.유향 그래프는 흐름 네트워크로 볼 수 있으며, 각 에지에 용량이 정해져 있고, 어떤 흐름이 그래프 상을 흐른다. 그래프의 시작점에서 종점까지의 최대 유량 문제를 푸는 알고리즘으로는 포드-풀커슨 알고리즘이 있다.
4. 2. 1. 너비 우선 탐색 (BFS, Breadth-First Search)
너비 우선 탐색(BFS)은 연결 요소의 모든 노드를 탐색하는 데 사용되는 방법 중 하나로, 루트 노드에서 시작한다.[14] 깊이 우선 탐색(DFS)과 함께 널리 사용된다.그래프 관련 알고리즘은 매우 많으며, 널리 연구되고 있다. 두 노드 간의 경로를 찾는 것은 그래프 관련 작업의 일반적인 예시이다. 깊이 우선 탐색이나 너비 우선 탐색 같은 기법을 사용하여 어떤 노드에서 다른 노드로 가는 최단 경로 문제를 해결할 수 있다. 다익스트라 알고리즘이 그 예시이다.
4. 2. 2. 깊이 우선 탐색 (DFS, Depth-First Search)
너비 우선 탐색(BFS)과 깊이 우선 탐색(DFS)은 주어진 연결 요소의 모든 노드를 탐색하는 데 사용되는 두 가지 접근 방식이다. 둘 다 임의의 노드, 즉 "루트"에서 시작한다.[14] 그래프 관련 알고리즘은 매우 많으며, 널리 연구되고 있다. 그래프 관련 전형적인 작업으로는 두 노드 간의 경로를 찾는 것이 있다. 깊이 우선 탐색이나 너비 우선 탐색 같은 기법을 사용하여 어떤 노드에서 다른 노드로 가는 최단 경로를 구한다.4. 3. 최단 경로 알고리즘
최단 경로를 찾는 알고리즘은 주어진 두 꼭짓점 사이의 최단 경로를 찾는 문제에 사용된다. 다익스트라 알고리즘과 플로이드-워셜 알고리즘 등이 널리 쓰인다. 깊이 우선 탐색이나 너비 우선 탐색과 같은 기법을 사용하여 특정 노드에서 다른 노드로의 최단 경로를 구할 수 있다.[1] 플로이드-워셜 알고리즘은 모든 노드 쌍에 대한 최단 경로를 찾는다.[1]4. 4. 최대 유량 알고리즘
유향 그래프는 흐름 네트워크로 볼 수 있으며, 각 에지에 용량이 정해져 있고, 어떤 흐름이 그래프 상을 흐른다.[1] 그래프의 시작점에서 종점까지의 최대 유량 문제를 푸는 알고리즘으로는 포드-풀커슨 알고리즘이 있다.[1]5. 병렬 그래프 표현
병렬 아키텍처에 사용되는 그래프 표현은 데이터 기반 계산, 비정형 문제, 낮은 지역성, 높은 데이터 접근 대 계산 비율과 같은 과제에 대처하는 데 중요한 역할을 한다.[8][9] 잘못된 표현은 알고리즘의 통신 비용을 불필요하게 증가시켜 확장성을 감소시킬 수 있다.
공유 메모리 모델의 경우, 병렬 처리에 사용되는 그래프 표현은 순차적인 경우와 동일하다.[10] 인접 리스트와 같은 공유 메모리에서 그래프 표현에 대한 병렬 읽기 전용 접근이 효율적이기 때문이다.
분산 메모리 모델에서는 그래프의 정점 집합 를 사용 가능한 처리 요소(PE)의 수 개의 집합 로 분할한다. 분할된 정점 집합은 해당 간선과 함께 일치하는 인덱스를 가진 PE에 분산된다. 각 PE는 자체 부분 그래프 표현을 가지며, 다른 분할에 끝점을 가진 간선은 특별한 주의가 필요하다. MPI와 같은 표준 통신 인터페이스를 사용하는 경우, 다른 끝점을 소유한 PE의 ID를 식별할 수 있어야 한다. 분산 그래프 알고리즘에서 이러한 간선을 따라 정보를 전달하는 것은 통신을 의미한다.[10]
그래프 분할은 통신량 감소와 균등한 크기 분할 사이의 상충 관계를 고려하여 신중하게 수행해야 한다.[11] 그러나 그래프 분할은 NP-hard 문제이므로, 다음과 같은 휴리스틱이 사용된다.
- 1D 분할: 각 프로세서는 개의 정점과 해당 발신 간선을 얻는다. 이는 인접 행렬의 행별 또는 열별 분해로 이해할 수 있다. 이 경우 각 PE가 잠재적으로 다른 모든 PE로 발신 간선을 가질 수 있으므로 All-to-All 통신 단계와 메시지 버퍼 크기가 필요하다.[12]
- 2D 분할: 각 프로세서는 인접 행렬의 부분 행렬을 얻는다. 프로세서가 직사각형 로 정렬되어 있다고 가정하면( 와 는 각각 각 행과 열의 처리 요소 수), 각 프로세서는 차원의 인접 행렬의 부분 행렬을 얻는다. 이는 행렬의 체커보드 패턴으로 시각화할 수 있다.[12] 각 처리 장치는 동일한 행과 열의 PE로만 발신 간선을 가질 수 있으므로, 각 PE에 대한 통신 파트너 수는 개로 제한된다.
6. 압축된 그래프 표현
그래프는 수조 개의 간선을 가질 수 있으며, 이는 기계 학습, 소셜 네트워크 분석 및 기타 분야에서 발생한다. 압축된 그래프 표현은 입출력 및 메모리 요구 사항을 줄이기 위해 개발되었다. 허프만 코딩과 같은 일반적인 기술을 적용할 수 있지만, 인접 리스트 또는 인접 행렬을 특정 방식으로 처리하여 효율성을 높일 수 있다.[13]
참조
[1]
서적
Operations on graphs
[2]
서적
[3]
서적
[4]
서적
Exercise 22.1-7
[5]
서적
Introduction to Algorithms
MIT Press and McGraw-Hill
[6]
서적
Algorithm Design and Applications
Wiley
[7]
서적
Introduction to Algorithms
Massachusetts Institute of Technology
[8]
서적
Graph Partitioning and Graph Clustering
https://www.ams.org/[...]
American Mathematical Society
2013-01
[9]
간행물
Challenges in Parallel Graph Processing
2007-03
[10]
서적
Sequential and Parallel Algorithms and Data Structures: The Basic Toolbox
https://www.springer[...]
Springer International Publishing
2019
[11]
웹사이트
Parallel Processing of Graphs
https://www.grapheng[...]
2020-03-09
[12]
conference
Parallel breadth-first search on distributed memory systems
2011
[13]
arXiv
Survey and Taxonomy of Lossless Graph Compression and Space-Efficient Graph Representations
2019-04-27
[14]
간행물
Graph Traversals and its Applications
http://ijrar.com/upl[...]
2018-07
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com