정점(vertex, node)과 그것을 이어주는 간선(edge)으로 구성된 자료구조다.
트리는 Acyclic 그래프다. 그래프가 네트워크적 관계를 보여주는 모델이라면, 트리는 계층관계를 보여주는 모델이다.
V: 정점의 개수, E: 간선의 개수
정점간의 연결 여부를 (0|1)로 표현한다.
eg) 1번 정점과 2번 정점은 연결되지 않은 경우
eg) 1번 정점과 3번 정점은 연결된 경우
간선의 개수와는 무관하며, V2를 가진다.
두 정점의 연결 여부 확인: O(1)
한 정점이 어느 정점과 연결되었는지 확인: O(V)
모든 정점에 대해 어느 정점과 연결되었는지 확인: O(V2)
각 정점이 어떤 정점과 인접한지를 표현한다. 즉, 정점마다 가진 리스트에 자신과 인접한 다른 정점들을 가진다.
eg) 1번 정점에 3,5,8번 정점이 연결된 경우
adjList[1] = [3, 5, 8]
O(E+V). 정점의 수만큼 공간이 필요하며, 간선의 수만큼 추가 공간이 요구된다.
두 정점의 연결 여부 확인: O(E)
한 정점이 어느 정점과 연결되었는지 확인: O(E)
모든 정점에 대해 어느 정점과 연결되었는지 확인: O(E)
한 정점으로부터 연결되어 있는 다른 한 정점으로 쭉 탐색한다. 탐색 도중 연결할 수 있는 정점이 하나도 없어지면, 전 단계의 정점으로 돌아가서 연결할 수 있는 다른 정점이 있는지 다시 탐색한다. 구현 시 주로 재귀 또는 스택을 이용한다.
한 정점으로부터 연결된 모든 정점으로 탐색한다. 즉, 한 정점으로부터 거리가 1인 모든 정점들을 탐색하고, 이후 거리가 2인 모든 정점들을 탐색하고, ...의 방식이다. 구현 시 주로 큐를 이용한다. BFS를 이용하면 최단 경로를 구할 수 있다.
그래프의 모든 정점이 acyclic하게 연결된 형태를 'Spanning Tree'라고 한다. 이러한 Spanning Tree 중 간선들의 가중치의 합이 최소가 되도록 하는 것이 MST(Minimum Spanning Tree, 최소 신장 트리)다. 즉 간선의 개수는 (정점의 개수 - 1) 이 된다. 일반적으로 크루스칼 알고리즘과 프림 알고리즘을 통해 구할 수 있다.
간선들을 가중치 기준 오름차순으로 정렬한다. 이 후, cycle을 이루지 않는 한에서 간선을 가중치가 낮은 순으로 선택한다.
알고리즘 세부 사항
새로운 간선이 Cycle을 이루는지 아닌지는 Union-Find 알고리즘을 통해 확인 가능하다. Union-Find는 말해, 어떤 원소가 어느 집합에 속했는지를 알 수 있게 해준다. 즉 정점을 원소, sub-graph를 집합이라 하면, 새로운 간선이 포함하는 두 정점이 같은 sub-graph에 있다면 해당 간선은 cycle을 이루기 때문에 MST에 포함될 수 없다. 일반적으로 트리를 통해 구현한다.
하나의 정점을 무작위로 선택한다. 그 후 해당 정점에서 연결된 간선들 중 가장 가중치가 낮은 간선을 선택하여 연결된 정점을 sub-graph에 포함한다. 이 후 sub-graph에 포함된 정점들과 연결된 다른 정점들 중 연결하는 간선의 가중치가 가장 낮은 정점을 선택하여 sub-graph에 포함한다. 우선순위 큐를 사용한다면 빠르게 sub-graph와 최소 간선을 통해 연결된 정점을 알 수 있다.
sub-graph 내의 모든 정점에 대해 최소 간선으로 연결된 다른 정점을 찾는 비용: O(V log V)
sub-graph와 간선으로 이어진 다른 정점들을 우선순위 큐에 삽입하고, 힙 내부에서 들어온 정점들을 정렬하는 비용: O(E log V)
일반적으로 V가 E보다 작다.
➡️ 총 시간 복잡도: O(E log V)
최소 힙을 사용하지 않고 일반적인 배열을 사용할 경우, O(V2)이 된다.
그래프 내의 간선이 많은 경우 프림(O(E log V)), 간선이 적을 경우 크루스칼 알고리즘(O(E log E))이 유리하다.