유니온 파인드(Union-Find)

Updated:

유니온 파인드(Union-Find)

유니온 파인드란?

▷ 대표적 그래프 알고리즘으로 ‘합집합 찾기’라는 의미를 가지고 있습니다.

▷ 상호 배타적 집합(Disjoint-set)이라고도 합니다.

▷ 여러 노드가 존재할 때, 두 개의 노드를 선택해서, 현재 두 노드가 서로 같은 그래프에 속하는지 판별하는 알고리즘입니다.

▷ 2가지 연산으로 이루어져 있습니다.

▶ Find : x가 어떤 집합에 포함되어 있는지 찾는 연산

▶ Union : x와 y가 포함되어 있는 집합을 합치는 연산



collection

위와 같이, 모두 연결되지 않고 각자 자기 자신만을 집합의 원소로 가지고 있을 때, 모든 값이 자기 자신을 가리키도록 만듭니다.

i : 노드번호, P[i] : 부모 노드 번호 를 의미하며, 즉 자기 자신이 어떤 부모에 포함되어 있는지를 의미합니다.

정리하면, Parent[i] = i로 간단히 표현할 수 있습니다.

collection

Union(1,2); Union(3,4) 를 해주어 위와 같이 노드를 연결해봅시다.

collection

위와 같이 표에 표현이 됩니다. 2번째 인덱스에 ‘1’이 들어가고, 4번 인덱스에 ‘3’이 들어가는 것을 보실 수 있습니다.

이와 같이 부모를 합칠 때는 일반적으로 더 작은 값 쪽으로 합칩니다. 이것을 합침(Union) 과정이라고 말할 수 있습니다.

collection

위와 같이 1, 2, 3이 연결될 때는 어떻게 표현이 될까요?? 바로 아래와 같이 표현이 됩니다.

collection

1과 3은 부모가 다르기 때문에 ‘1과 3이 연결되었는지’ 파악하기 힘이 듭니다. 이에 재귀함수가 사용됩니다.

3의 부모인 2를 먼저 찾고, 2의 부모인 1을 찾아, 결과적으로 3의 부모는 1이 되는 것을 파악하는 것입니다.

Union의 과정이 수행된 후에는 다음과 같은 표로 바뀝니다.

collection

결국 1,2,3의 부모는 모두 1이기 때문에 이 세 가지 노드는 모두 같은 그래프에 속한다는 것을 알 수 있습니다.

해당 경로를 바꿔주는 과정은 아래와 같은 그림으로 변하게 됩니다.

collection

유니온파인드 code

public class Main {
    public static int[] parent = new int[1000001];

    public static int find(int x) {
        if(x == parent[x])
            return x;
        else
            return parent[x] = find(parent[x]);
	}

    public static void union(int x, int y) {
        x = find(x);
        y = find(y);
        // 같은 부모를 가지고 있지 않을 때
        if(x != y) {
            // y가 x 보다 크다는 것을 가정한다면 아래와 같이 표현
            parent[y] = x;
            // 더 작은 값으로 넣어 줄 때 다음과 같이도 표현 가능
            /*
            if(x < y) parent[y] = x;
            else parent[x] = y;
            */
        }
    }
    //같은 부모 노드를 가지는지 확인
    public static boolean isSameParent(int x, int y) {
        x = find(x);
        y = find(y);
        if(x == y)
            return true;
        else
            return false;
    }
    public static void main(String[] args) {
        for(int i = 1; i <= 8; i++) {
            parent[i] = i;
        }
        union(1, 2);
        union(2, 3);
        System.out.println("1과 3은 연결되어 있나요? " + isSameParent(1,3));
    }
}
1과 3은 연결되어 있나요? true

Leave a comment