
com.github.tommyettinger.gand.algorithms.MinimumWeightSpanningTree Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gand Show documentation
Show all versions of gand Show documentation
Pathfinding and other graph algorithms. Based on simple-graphs.
The newest version!
package com.github.tommyettinger.gand.algorithms;
import com.badlogic.gdx.utils.NumberUtils;
import com.github.tommyettinger.gand.Connection;
import com.github.tommyettinger.gand.Node;
import com.github.tommyettinger.gand.UndirectedGraph;
import com.github.tommyettinger.gand.ds.ObjectDeque;
public class MinimumWeightSpanningTree extends Algorithm{
private UndirectedGraph spanningTree;
private ObjectDeque> edgeQueue;
private int finishAt;
// adapted from https://www.baeldung.com/java-spanning-trees-kruskal
protected MinimumWeightSpanningTree(int id, UndirectedGraph graph, boolean minSpanningTree) {
super(id);
spanningTree = graph.createNew();
spanningTree.addVertices(graph.getVertices());
edgeQueue = new ObjectDeque<>(graph.internals().getConnections());
if(minSpanningTree)
edgeQueue.sort((a, b) -> NumberUtils.floatToIntBits(a.getWeight() - b.getWeight() + 0f));
else
edgeQueue.sort((a, b) -> NumberUtils.floatToIntBits(b.getWeight() - a.getWeight() + 0f));
finishAt = graph.isConnected() ? graph.size() - 1 : -1;
}
@Override
public boolean update() {
if (isFinished()) return true;
Connection edge = edgeQueue.poll();
if (doesEdgeCreateCycle(edge.getNodeA(), edge.getNodeB(), id)) {
return false;
}
spanningTree.addEdge(edge.getA(), edge.getB(), edge.getWeight());
return isFinished();
}
private void unionByRank(Node rootU, Node rootV) {
if (rootU.getIndex() < rootV.getIndex()) {
rootU.setPrev(rootV);
} else {
rootV.setPrev(rootU);
if (rootU.getIndex() == rootV.getIndex()) rootU.setIndex(rootU.getIndex() + 1);
}
}
private Node find(Node node) {
if (node.equals(node.getPrev())) {
return node;
} else {
return find(node.getPrev());
}
}
private Node pathCompressionFind(Node node) {
if (node.equals(node.getPrev())) {
return node;
} else {
Node parentNode = find(node.getPrev());
node.setPrev(parentNode);
return parentNode;
}
}
private boolean doesEdgeCreateCycle(Node u, Node v, int runID) {
if (u.resetAlgorithmAttribs(runID)) u.setPrev(u);
if (v.resetAlgorithmAttribs(runID)) v.setPrev(v);
Node rootU = pathCompressionFind(u);
Node rootV = pathCompressionFind(v);
if (rootU.equals(rootV)) {
return true;
}
unionByRank(rootU, rootV);
return false;
}
@Override
public boolean isFinished() {
return finishAt < 0 ? edgeQueue.isEmpty() : spanningTree.getEdgeCount() == finishAt;
}
public UndirectedGraph getSpanningTree() {
return spanningTree;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy