에듀테크 프로젝트 대시보드
유니온-파인드 (Union-Find)
여러 원소를 겹치지 않는 그룹(서로소 집합)으로 관리하면서 두 가지 질문에 빠르게 답하는 자료구조다.
find(x) — x가 속한 그룹의 대표(루트)는? union(a, b) — a와 b의 그룹을 하나로 합쳐라.
각 그룹을 부모 포인터로 이어진 트리로 표현하고, union by rank(낮은 트리를 높은 트리 밑에 붙이기)와
path compression(찾은 경로의 노드를 루트에 바로 연결)을 함께 쓰면
연산 한 번이 사실상 상수 시간 O(α(n)) 에 끝난다.
class DisjointSet: def __init__(self, n): self.parent = list(range(n)) # 처음엔 각자 자기 자신이 루트 self.rank = [0] * n def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) # path compression return self.parent[x] def union(self, a, b): ra, rb = self.find(a), self.find(b) if ra == rb: return False # 이미 같은 그룹 (사이클!) if self.rank[ra] < self.rank[rb]: ra, rb = rb, ra # 항상 rank 큰 쪽을 부모로 self.parent[rb] = ra if self.rank[ra] == self.rank[rb]: self.rank[ra] += 1 return True
find 가 O(n) 까지 나빠진다.O(α(n)) — α는 아커만 함수의 역함수로, 현실적인 n에서는 4 이하 (사실상 상수).find 로 다른 그룹일 때만 채택하고 union. 같은 그룹이면 사이클이 생기므로 건너뛴다.union 이 False 를 반환하면 그 간선이 사이클을 만든다는 뜻.find(A) == find(B).| 방법 | find 한 번 비용 | 비고 |
|---|---|---|
| 순진한 트리 | O(n) | 한 줄로 늘어질 수 있음 |
| + union by rank | O(log n) | 트리 높이 제한 |
| + path compression | O(α(n)) ≈ O(1) | 사실상 상수 |