Prim의 알고리즘은 가중된 무방향 그래프에 대한 최소 스패닝 트리를 찾는 욕심 많은 알고리즘입니다. 모든 정점을 포함하는 트리를 형성하는 가장자리의 하위 집합을 찾습니다. 여기서 트리의 모든 가장자리의 총 가중치는 최소화됩니다.
이 알고리즘은 각 단계에서 임의의 시작 정점에서 한 번에 하나의 정점을 트리에서 다른 정점으로 가장 저렴한 연결을 추가하여 이 트리를 구축하는 방식으로 작동합니다.
Prim의 알고리즘은 어떻게 작동합니까?
Prim의 알고리즘이 작동하는 방식에 대한 그림을 살펴보겠습니다. -
1. 임의의 노드를 루트 노드로 선택합니다. 이 경우 S 노드를 Prim의 스패닝 트리의 루트 노드로 선택합니다. 이 노드는 임의로 선택되므로 모든 노드가 루트 노드가 될 수 있습니다. 모든 비디오가 루트 노드가 될 수 있는 이유가 궁금할 수 있습니다. 따라서 답은 스패닝 트리에 그래프의 모든 노드가 포함되어 있고 연결되어 있기 때문에 트리의 나머지 부분에 연결하는 가장자리가 최소한 하나는 있어야 한다는 것입니다.
2. 나가는 간선을 확인하고 비용이 덜 드는 간선을 선택합니다. 루트 노드 S를 선택한 후 S, A, S, C가 각각 가중치가 7과 8인 두 개의 간선임을 알 수 있습니다. 우리는 가장자리 S, A가 다른 것보다 작기 때문에 선택합니다.
이제 트리 S-7-A는 하나의 노드로 취급되며 여기서 나가는 모든 가장자리를 확인합니다. 비용이 가장 저렴한 것을 선택하여 트리에 포함시킵니다.
이 단계 후에 S-7-A-3-C 트리가 형성됩니다. 이제 다시 노드로 처리하고 모든 가장자리를 다시 확인합니다. 그러나 우리는 가장 비용이 적게 드는 가장자리만 선택할 것입니다. 이 경우 C-3-D는 다른 가장자리의 비용 8, 6, 4 등보다 적은 새 가장자리입니다.
노드 D를 추가한 후 스패닝 트리에 대해 이제 동일한 비용을 갖는 두 개의 모서리, 즉 D-2-T 및 D-2-B가 있습니다. 따라서 둘 중 하나를 추가할 수 있습니다. 그러나 다음 단계는 다시 가장자리 2를 최소 비용으로 산출합니다. 따라서 우리는 양쪽 가장자리가 포함된 스패닝 트리를 보여주고 있습니다.
이제 코드에서 동일하게 구현하는 방법을 살펴보겠습니다.
예시
primsMST() { // Initialize graph that'll contain the MST const MST = new Graph(); if (this.nodes.length === 0) { return MST; } // Select first node as starting node let s = this.nodes[0]; // Create a Priority Queue and explored set let edgeQueue = new PriorityQueue(this.nodes.length * this.nodes.length); let explored = new Set(); explored.add(s); MST.addNode(s); // Add all edges from this starting node to the PQ taking weights as priority this.edges[s].forEach(edge => { edgeQueue.enqueue([s, edge.node], edge.weight); }); // Take the smallest edge and add that to the new graph let currentMinEdge = edgeQueue.dequeue(); while (!edgeQueue.isEmpty()) { // COntinue removing edges till we get an edge with an unexplored node while (!edgeQueue.isEmpty() && explored.has(currentMinEdge.data[1])) { currentMinEdge = edgeQueue.dequeue(); } let nextNode = currentMinEdge.data[1]; // Check again as queue might get empty without giving back unexplored element if (!explored.has(nextNode)) { MST.addNode(nextNode); MST.addEdge(currentMinEdge.data[0], nextNode, currentMinEdge.priority); // Again add all edges to the PQ this.edges[nextNode].forEach(edge => { edgeQueue.enqueue([nextNode, edge.node], edge.weight); }); // Mark this node as explored explored.add(nextNode); s = nextNode; } } 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.primsMST().display();
출력
이것은 출력을 줄 것입니다 -
A->B, D B->A, G D->A, C, E C->D E->D, F G->B F->E
초기 그래프는 -
예시
/** * A * / | \ * C | B * \ | | * D G * | / * E * | * F */
출력
현재 그래프는 다음과 같습니다. -
/** * A * |\ * C | B * \ | | * D G * | * E * | * F * */
가장 값비싼 모서리를 제거하고 이제 스패닝 트리를 갖게 되었습니다.