-
Kruskal 알고리즘알고리즘 2020. 5. 3. 18:59
Programmers의 Greedy Kits 중 [섬 연결하기] 문제를 풀다가 좋은 방법이 없을까? 해서 찾게된 알고리즘.
Kruskal 알고리즘이란?
Greedy method를 이용하여 가중치를 간선에 할당한 그래프의 모든 정점을 최소 비용으로 연결하는 최적 해를 구하는 알고리즘
👉 Greedy method: 결정을 해야 할 때마다, 그 순간에 가장 좋다고 생각하는 것을 선택하며 최종적인 해답에 도달하는 것. 반드시 검증이 필요하다.
👉 최소 비용 신장트리 만드는 법: 1) 최소 비용의 간선으로 구성되며, 1) 사이클을 포함하지 않음의 조건에 근거해서 각 단계에서 사이클을 이루지 않는 최소 비용 간선을 선택.
Kruskal 알고리즘의 동작
1. 그래프들의 간선들을 가중치의 오름차순으로 정렬
2. 정렬된 간선 리스트에서 순서대로 사이클을 형성하지 않는 간선을 선택
- 즉, 가장 낮은 가중치를 먼저 선택
- 사이클을 형성하는 간선은 제외 (사이클 형성하는지는 어떻게 알지? 🤷🏻♀️)
3. 해당 간선을 현재의 MST(최소 비용 신장 트리)의 집합에 추가
🤷🏻♀️ 사이클을 생성하는지는 어떻게 체크할까? 🤷🏻♀️
- 추가할 새로운 간선의 양 끝 정점이 같은 집합에 속해 있으면 사이클이 형성된다.
- union-find 알고리즘을 이용
union-find 알고리즘
union-find 알고리즘을 알기 위해서는 먼저 Disjoint Set이라는 자료구조를 먼저 알아야 한다.
Disjoint Set이란?
서로 중복되지 않는 부분 집합들로 나눠진 원소들에 대한 정보를 저장하고 조작하는 자료구조. (서로소 집합 자료구조)
union-find란?
집합을 트리구조를 이용하여 구현.
아래의 세 가지 연산을 이용하여 Disjoint Set을 표현한다.
● make-set(x): 초기화. x를 유일한 원소로 하는 새로운 집합을 생성.
● union(x, y): 합치기. x가 속한 집합과 y가 속한 집합을 합친다.
● find(x): 찾기. x가 속한 집합의 루트 노드 값을 반환한다. 즉, x가 어떤 집합에 속해 있는지 찾는 연산
union-find의 기본적인 구현 방법
/* 초기화 */ int root[MAX_SIZE]; for (int i = 0; i < MAX_SIZE; i++) parent[i] = i; /* find(x): 재귀 이용 */ int find(int x) { if (root[x] == x) { return x; } else { return find(root[x]); } } /* union(x, y) */ void union(int _x, int _y){ int x = find(_x); int y = find(_y); root[y] = x; }
위의 구현 방법은 기본 적인 구현 방법이며, 최적화를 위해서는 아래와 같은 코드를 사용한다.
find 연산 최적화
경로를 압축. 시간 복잡도는 O(logN)의 값을 가진다.
int find(int x) { if (root[x] == x) { return x; } else { // find 하면서 만난 모든 값의 부모 노드를 root로 만든다. return root[x] = find(root[x]); } }
union 연산 최적화
rank에 트리의 높이를 저장한 후, 항상 높이가 더 낮은 트리를 높은 트리 밑에 넣는다.
void union(int x, int y){ x = find(x); y = find(y); // 두 값의 root가 같으면(이미 같은 트리) 합치지 않는다. if(x == y) return; // 항상 높이가 더 낮은 트리를 높이가 높은 트리 밑에 넣는다. 즉, 높이가 더 높은 쪽을 root로 if(rank[x] < rank[y]) { root[x] = y; // x의 root를 y로 변경 } else { root[y] = x; // y의 root를 x로 변경 if(rank[x] == rank[y]) rank[x]++; // 만약 높이가 같다면 합친 후 (x의 높이 + 1) } }
'알고리즘' 카테고리의 다른 글
javascript로 알고리즘 풀 때 유용한 메소드를 정리해보자 (0) 2020.05.10 BFS 알고리즘 (2) 2020.04.17