Graph
Graph
- 우리가 흔히 생각하는 ‘그래프(chart)’가 아니라, 요소 간의 관계를 표현하는 자료구조임.
- 여러 요소가 어떻게 연결되어 있는지를 표현함.
- 예시: SNS에서 사용자는 서로 팔로우하거나 팔로우당함 → 단순 배열이나 트리로는 표현이 어려움.
그래프의 정의
그래프는 (V, E)로 구성됨:
- V: 노드 집합
- E: 노드 쌍의 집합 (간선)
방향 그래프 (Directed Graph)
간선에 방향이 있음: (u, v)는 u에서 v로의 연결을 의미함.
가중치 그래프 (Weighted Graph)
각 간선에 실수 값(weight)을 부여함: (V, E, W)
그래프 관련 용어
- Degree (차수): 한 노드에 연결된 간선 수
- 이분 그래프 (Bipartite): 노드를 두 그룹으로 나누고, 그룹 간에만 연결 존재
- 완전 그래프 (Complete Graph): 모든 노드 쌍이 연결됨
- 클리크 (Clique): 완전 부분 그래프
그래프 표현 방법
인접 행렬 (Adjacency Matrix)
정방형 행렬로 표현
- 장점: 접근 용이
- 단점: 공간 낭비 (특히 희소 그래프에서)
인접 리스트 (Adjacency List)
각 노드가 연결된 이웃 노드를 리스트로 저장
- 장점: 메모리 효율적
- 단점: 구조가 일정하지 않음
희소 vs 밀집 그래프
희소(Sparse) 그래프: 대부분의 노드가 적은 수의 연결만 가짐 (예: Twitter)
밀집(Dense) 그래프: 대부분의 노드가 서로 많이 연결되어 있음
그래프 연산
- 속성 질의 → 방향성 여부, 가중치 여부, 노드/간선 수
- 수정 → 노드/간선 추가, 가중치 변경 등
- 탐색 → 노드/간선/가중치 조회
그래프 순회 (Traversal)
트리와 다르게 루트가 없음 → 임의의 시작점에서 순회 시작
- DFS (깊이 우선 탐색): 가능한 깊게 들어감
- BFS (너비 우선 탐색): 가능한 넓게 퍼짐
DFS 예시
스택 또는 재귀 사용 → 무한 루프 방지를 위해 방문 체크 필요
BFS 예시
큐 사용 → 각 레벨의 노드를 모두 방문 후 다음으로 진행
연결 요소 (Connected Components)
노드들이 연결된 “덩어리”
- 서로 연결되지 않은 노드 집합은 서로 다른 컴포넌트임
- 그래프에서 독립된 섬처럼 존재함
스패닝 트리 (Spanning Tree)
그래프에서 모든 노드를 포함하면서 사이클이 없는 트리
- 여러 개의 스패닝 트리 가능
최소 신장 트리 (Minimum Spanning Tree, MST)
- 스패닝 트리 중 가중치의 합이 가장 작은 것 → 브루트 포스로 찾기는 매우 비효율적
MST 알고리즘
Prim’s Algorithm
임의의 노드에서 시작해 가장 가중치가 작은 간선을 계속 연결 → 최소 힙 또는 우선순위 큐 사용
- Top-down 방식
Prim’s Algorithm Output
- Output은 최소 신장 트리 (Minimum Spanning Tree, MST)입니다. 즉, 그래프 내 모든 노드를 연결하면서 전체 가중치 합이 최소인 트리 구조가 결과로 나옵니다.
사용할 자료구조 (DS)
-
후보 간선을 저장하는 리스트 C: → 최소 힙 (Min Heap / Priority Queue) 사용 → 각 간선 <v, u, w>를 넣되, 가중치 w가 가장 작은 것부터 꺼낼 수 있도록 함.
-
방문 여부 체크를 위한 집합 visited: → 중복 방문 방지 및 사이클 방지를 위해 필요
-
간선 정보를 저장할 그래프 구조: → 인접 리스트 (Adjacency List) 또는 인접 행렬 사용 가능
시간 복잡도 (Time Complexity) 일반적인 구현 → 우선순위 큐 사용
- 노드 수: 𝑉
- 간선 수: 𝐸
- 시간 복잡도: 𝑂(𝐸 log 𝑉)
- 이유: 최대 𝐸개의 간선을 우선순위 큐에 넣고 꺼내는 연산이 있으므로 log 𝑉 만큼의 비용이 듬.
Kruskal’s Algorithm
가중치가 가장 작은 간선부터 선택하면서 사이클을 만들지 않도록 트리를 점점 확장해 나감
→ 시작 노드 없이 간선 위주로 트리를 구성
- Bottom-up 방식
Kruskal’s Algorithm Output
- 입력: 가중치가 있는 무방향 그래프 G = {V, E, W}
- Output은 최소 신장 트리 (Minimum Spanning Tree, MST)입니다. 즉, 그래프 내 모든 노드를 연결하면서 전체 가중치 합이 최소인 트리 구조가 결과로 나옵니다.
사용할 자료구조 (DS)
-
가중치 기준 정렬된 간선 리스트 → 입력된 모든 간선을 <v, u, w> 형태로 오름차순 정렬하여 저장 아마 우선순위 큐(Heap)같은거 써야하지 않을까 싶음.
-
트리 병합을 위한 트리 ID 추적 구조 (예: 딕셔너리): → 각 노드가 어떤 트리에 속해 있는지를 저장 (예: tree_id[node] = id) → 두 노드가 서로 다른 트리에 속한 경우 병합 처리 (모든 관련 노드의 ID 갱신 필요)
-
간선 정보를 저장할 그래프 구조: → 인접 리스트 또는 간선 집합 (T) 형태로 저장 가능
시간 복잡도 (Time Complexity) Union-Find 없이 구현한 경우 기준
- 노드 수: 𝑉
- 간선 수: 𝐸
- 시간 복잡도:
- 간선 정렬: O(𝐸 log 𝐸)
- 트리 병합 (최악의 경우): O(𝐸 × 𝑉)
- 총 시간 복잡도: O(𝐸 log 𝐸 + 𝐸 × 𝑉)
- 이유: 정렬은 한 번만 수행되지만, 트리 병합 시 각 노드의 트리 ID를 모두 갱신해야 할 수 있기 때문
Leave a comment