// Time: V^2 x V
function prim(edges) {
if (edges.length < 2)
return [];
const answer = new Array(edges.length);
// fill weights
for (let vertex = 0; vertex < edges.length; vertex++) {
answer[vertex] = new Array();
}
const visited = new Array(edges.length).fill(false);
let componentCount = 0;
// V
for (let vertex = 0; vertex < edges.length; vertex++) {
if (visited[vertex] === true)
continue;
// V^2
findMSTWithPriorityQueue(edges, answer, visited, vertex);
componentCount += 1;
}
if (componentCount > 1) {
console.log('edges forms a minimum spanning FOREEST not TREE');
}
return answer;
}
function findMSTWithPriorityQueue(edges, answer, visited, start) {
// E
const arr = [];
for (const [next, w] of edges[start]) {
arr.push([w, start, next]);
}
const predicate = (arr, a, b) => arr[a][0] <= arr[b][0];
const minHeap = new MinHeap(arr, predicate);
visited[start] = true;
console.log('heap:: ', minHeap.heap);
// cnt > cnt of vertices V
let cnt = 1;
while (minHeap.heap.length !== 0 && cnt < edges.length) {
// V
const [w, here, there] = minHeap.remove(); // LogV
if(visited[there] === true)
continue;
answer[here].push([there, w]);
answer[there].push([here, w]);
// E
for (const [next, w] of edges[there]) {
if (visited[next] === true) continue;
minHeap.insert([w, there, next]); // logV
}
visited[there] = true;
cnt++;
}
}
class MinHeap {
constructor(arr, predicate = (a, b) => a <= b) {
this.predicate = predicate;
this.heap = this.buildHeap(arr);
}
buildHeap(arr) {
let currentIndex = Math.floor((arr.length - 1 - 1) / 2);
while (currentIndex >= 0) {
this.siftDown(arr, currentIndex, arr.length - 1);
currentIndex -= 1;
}
console.log('>>> ', arr);
return arr;
}
siftDown(heap, currentIndex, endIndex) {
let left = currentIndex * 2 + 1;
while (left <= endIndex) {
let min = left;
const right = currentIndex * 2 + 2;
if (heap[right] !== undefined && this.predicate(heap, right, min)) {
min = right;
}
if (this.predicate(heap, currentIndex, min))
break;
this.swap(heap, min, currentIndex);
currentIndex = min;
left = currentIndex * 2 + 1;
}
}
siftUp(heap, currentIndex) {
let parentIndex = Math.floor((currentIndex - 1) / 2);
while (parentIndex >= 0) {
if (this.predicate(heap, parentIndex, currentIndex))
break;
this.swap(heap, parentIndex, currentIndex);
currentIndex = parentIndex;
parentIndex = Math.floor((currentIndex - 1) / 2);
}
}
insert(v) {
this.heap.push(v);
this.siftUp(this.heap, this.heap.length - 1);
}
remove() {
this.swap(this.heap, 0, this.heap.length - 1);
const elementToRemove = this.heap.pop();
this.siftDown(this.heap, 0, this.heap.length - 1);
return elementToRemove;
}
swap(arr, a, b) {
const temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
}
// Do not edit the line below.
exports.kruskalsAlgorithm = kruskalsAlgorithm;