Kruskal의 알고리즘은 다음과 같이 작동하는 욕심 많은 알고리즘입니다 -
1. 그래프의 모든 간선 세트를 생성합니다.
2. 위의 집합이 비어 있지 않고 모든 정점이 포함되는 것은 아니지만
- 이 세트에서 최소 가중치 가장자리를 제거합니다.
- 이 에지가 순환을 형성하는지 아니면 2개의 나무를 연결하는지 확인합니다. 순환을 형성하면 이 모서리를 버리고, 그렇지 않으면 트리에 추가합니다.
3. 위의 처리가 완료되면 최소 스패닝 트리가 생깁니다.
이 알고리즘을 구현하려면 2개의 데이터 구조가 더 필요합니다.
먼저 가장자리를 정렬된 순서로 유지하고 각 반복에서 필요한 가장자리를 얻는 데 사용할 수 있는 우선 순위 대기열이 필요합니다.
다음으로, 분리된 집합 데이터 구조가 필요합니다. disjoint-set 데이터 구조(union-find 데이터 구조 또는 merge-find set이라고도 함)는 여러 개의 disjoint(비중첩) 하위 집합으로 분할된 요소 집합을 추적하는 데이터 구조입니다. 트리에 새 노드를 추가할 때마다 이미 연결되어 있는지 확인합니다. 그렇다면 주기가 있습니다. 그렇지 않은 경우 가장자리의 두 정점을 합집합합니다. 그러면 동일한 하위 집합에 추가됩니다.
UnionFind 또는 DisjointSet 데이터 구조의 구현을 살펴보겠습니다. &minsu;
예시
class UnionFind {
constructor(elements) {
// Number of disconnected components
this.count = elements.length;
// Keep Track of connected components
this.parent = {};
// Initialize the data structure such that all
// elements have themselves as parents
elements.forEach(e => (this.parent[e] = e));
}
union(a, b) {
let rootA = this.find(a);
let rootB = this.find(b);
// Roots are same so these are already connected.
if (rootA === rootB) return;
// Always make the element with smaller root the parent.
if (rootA < rootB) {
if (this.parent[b] != b) this.union(this.parent[b], a);
this.parent[b] = this.parent[a];
} else {
if (this.parent[a] != a) this.union(this.parent[a], b);
this.parent[a] = this.parent[b];
}
}
// Returns final parent of a node
find(a) {
while (this.parent[a] !== a) {
a = this.parent[a];
}
return a;
}
// Checks connectivity of the 2 nodes
connected(a, b) {
return this.find(a) === this.find(b);
}
} −
를 사용하여 이것을 테스트할 수 있습니다.예시
let uf = new UnionFind(["A", "B", "C", "D", "E"]);
uf.union("A", "B"); uf.union("A", "C");
uf.union("C", "D");
console.log(uf.connected("B", "E"));
console.log(uf.connected("B", "D")); 출력
이것은 출력을 줄 것입니다 -
false true
이제 이 데이터 구조를 사용하여 Kruskal 알고리즘의 구현을 살펴보겠습니다.
예시
kruskalsMST() {
// Initialize graph that'll contain the MST
const MST = new Graph();
this.nodes.forEach(node => MST.addNode(node));
if (this.nodes.length === 0) {
return MST;
}
// Create a Priority Queue
edgeQueue = new PriorityQueue(this.nodes.length * this.nodes.length);
// Add all edges to the Queue:
for (let node in this.edges) {
this.edges[node].forEach(edge => {
edgeQueue.enqueue([node, edge.node], edge.weight);
});
}
let uf = new UnionFind(this.nodes);
// Loop until either we explore all nodes or queue is empty
while (!edgeQueue.isEmpty()) {
// Get the edge data using destructuring
let nextEdge = edgeQueue.dequeue();
let nodes = nextEdge.data;
let weight = nextEdge.priority;
if (!uf.connected(nodes[0], nodes[1])) {
MST.addEdge(nodes[0], nodes[1], weight);
uf.union(nodes[0], nodes[1]);
}
}
return MST;
} −
를 사용하여 이것을 테스트할 수 있습니다.예시
let g = new Graph();
g.addNode("A");
g.addNode("B");
g.addNode("C");
g.addNode("D");
g.addNode("E");
g.addNode("F");
g.addNode("G");
g.addEdge("A", "C", 100);
g.addEdge("A", "B", 3);
g.addEdge("A", "D", 4);
g.addEdge("C", "D", 3);
g.addEdge("D", "E", 8);
g.addEdge("E", "F", 10);
g.addEdge("B", "G", 9);
g.addEdge("E", "G", 50);
g.kruskalsMST().display(); 출력
이것은 출력을 줄 것입니다 -
A->B, D B->A, G C->D D->C, A, E E->D, F F->E G->B