let elesfn = ({ | |
// kruskal's algorithm (finds min spanning tree, assuming undirected graph) | |
// implemented from pseudocode from wikipedia | |
kruskal: function( weightFn ){ | |
weightFn = weightFn || ( edge => 1 ); | |
let { nodes, edges } = this.byGroup(); | |
let numNodes = nodes.length; | |
let forest = new Array(numNodes); | |
let A = nodes; // assumes byGroup() creates new collections that can be safely mutated | |
let findSetIndex = ele => { | |
for( let i = 0; i < forest.length; i++ ){ | |
let eles = forest[i]; | |
if( eles.has(ele) ){ return i; } | |
} | |
}; | |
// start with one forest per node | |
for( let i = 0; i < numNodes; i++ ){ | |
forest[i] = this.spawn( nodes[i] ); | |
} | |
let S = edges.sort( (a, b) => weightFn(a) - weightFn(b) ); | |
for( let i = 0; i < S.length; i++ ){ | |
let edge = S[i]; | |
let u = edge.source()[0]; | |
let v = edge.target()[0]; | |
let setUIndex = findSetIndex(u); | |
let setVIndex = findSetIndex(v); | |
let setU = forest[ setUIndex ]; | |
let setV = forest[ setVIndex ]; | |
if( setUIndex !== setVIndex ){ | |
A.merge( edge ); | |
// combine forests for u and v | |
setU.merge( setV ); | |
forest.splice( setVIndex, 1 ); | |
} | |
} | |
return A; | |
} | |
}); | |
export default elesfn; | |