서로소 집합이라고 불리우는 분리 집합은 중복되는 부분이 발생하지 않도록 모든 원소를 분리한 집합을 말한다. 그냥 서로 중복되지 않는 부분 집합들로 이루어진 원소들에 대해 저장하고 있는 자료구조이다.
유니온-파인드(Union-Find)는 분리 집합을 구현하는 알고리즘으로, 트리 구조로 표현하는 것이 가장 효율적이(라고 한)다.
먼저, 각 노드 별로 부모 노드 번호를 기록한다. 그럼 그래프가 트리 형태로 표현된다.
makeSet(x)초기화 작업. x를 유일한 원소로 하는 새로운 집합을 만든다.
var parent = Array(0...n)
find(x)x가 속한 집합의 대표 값인 root 노드를 반환한다. 즉, x가 어떤 집합, 어떤 그룹에에 속해 있는지 찾는다.
func find(_ x: Int) -> Int {
if x == parent[x] {
return x // 루트 노드는 부모 노드 번호가 자기 자신의 번호이다. 따라서 루트 노드이므로 리턴
} else {
return parent[x] // 부모 노드로 거슬러 올라가는 중........
}
}
func find(_ x: Int) -> Int {
if x != parent[x] {
parent[x] = find(parent[x])
}
return parent[x]
}
union(x, y)x가 속한 집합과 y가 속한 집합을 합친다. 즉, 두 개의 트리를 병합한다.
func union(_ x: Int, _ y: Int) {
let rootX = find(x)
let rootY = find(y)
if rootX != rootY {
parent[rootX] = rootY
}
}
var rank = [Int](repeating: 0, count: n + 1)
func union(_ x: Int, _ y: Int) {
var rootX = find(x)
var rootY = find(y)
if rootX != rootY {
if rank[rootX] < rank[rootY] {
parent[rootX] = rootY // 높이가 낮으면(작으면) 높이가 높은 데에 붙인다(부모 노드로 등록)
} else rank[rootX] > rank[rootY] {
parent[rootY] = rootX // 트리의 높이가 높은 쪽이 루트가 되는 셈
} else {
parent[rootX] = rootY // 높이가 같으면 일단 x의 부모를 y로 설정해서 트리를 합치고
rank[rootX] += 1 // 합친 트리의 높이 1 증가
}
}
}