알고리즘
[알고리즘] Kruscal 크루스칼 알고리즘
hyeonit
2024. 8. 31. 22:13
최소 신장 트리 (MST, Minimum Spanning Tree) 를 만들기 위한 대표적인 알고리즘 중 하나이다
특징
1. 그리디 알고리즘
- 크루스칼 알고리즘은 그리디 알고리즘의 일종으로 매 순간 최적의 선택을 하면서 전체 최적해를 찾는다
- 이 말은 즉, 간선의 가중치가 가장 작은 것부터 차례대로 선택하여 최소 신장 트리를 구성
2. 간선 중심!
- 간선의 가중치에 기반하여 간선을 선택한다
- 그래서 간선을 정렬한 후 가장 가중치가 작은 간선부터 선택하는 방식이다
3. 간선 수가 적을 때 효율적
- 간선의 수가 정점의 수에 비해 적을때 크루스칼 알고리즘이 효율적으로 동작한다
- 왜냐하면 전체 간선을 정렬한 후 선택하는 방식이기 때문이다
과정
1. 초기 상태는 정점은 서로 연결되어 있지 않는 상태이다
2. 간선을 하나씩 추가하면서 MST를 만든다
2-1. 크기가 가장 작은 간선부터 모든 간선을 본다
2-2. 가중치를 이용해 간선을 오름차순으로 정렬한다
-> 1, 2, 2, 4, 5, 7, 7
2-3. 가중치가 가장 적은 간선 부터 그래프에 추가한다
2-4. 추가 할때 MST에 사이클이 생기는지 확인 -> 여기에서 유니온 파인드 알고리즘을 이용함
2-5. 추가 할때 사이클이 생기지 않는다면 추가
2-6. 추가할때 사이클이 생긴다면 추가 하지않고 다음 간선을 본다
3. 이런식으로 2번을 반복하다가 정점이 다 이어져 있으면 종료를 한다 -> 이게 MST가 되는것이다.
코드 표현
import java.util.*;
public class Solution {
static int nodeCount = 5;
static int[] parents;
public static void main(String[] args) throws Exception {
Edge[] edgeArray = new Edge[7];
edgeArray[0] = new Edge(1, 4, 1);
edgeArray[1] = new Edge(1, 3, 7);
edgeArray[2] = new Edge(1, 2, 7);
edgeArray[3] = new Edge(2, 5, 2);
edgeArray[4] = new Edge(3, 4, 2);
edgeArray[5] = new Edge(3, 5, 4);
edgeArray[6] = new Edge(4, 5, 5);
Arrays.sort(edgeArray);
init();
int weightSum = 0;
for (Edge edge : edgeArray) {
if (union(edge.nodeA, edge.nodeB)) {
System.out.println(edge.nodeA + " -> " + edge.nodeB);
weightSum += edge.weight;
}
}
System.out.println(weightSum);
}
public static void init() {
parents = new int[nodeCount + 1];
for (int i = 1; i <= nodeCount; i++) {
parents[i] = i;
}
}
public static int findRoot(int a) {
if (parents[a] == a) {
return a;
}
return parents[a] = findRoot(parents[a]);
}
public static boolean union(int a, int b) {
int aRoot = findRoot(a);
int bRoot = findRoot(b);
if (aRoot == bRoot) {
return false;
}
parents[aRoot] = bRoot;
return true;
}
}
class Edge implements Comparable<Edge> {
int nodeA;
int nodeB;
int weight;
public Edge(int nodeA, int nodeB, int weight) {
this.nodeA = nodeA;
this.nodeB = nodeB;
this.weight = weight;
}
public int compareTo(Edge o) {
return this.weight - o.weight;
}
}
코드 실행 화면