BAEL-3883: Boruvka's minimum spanning tree, moved code to newer module (#8949)
algorithms-miscellaneous-6
This commit is contained in:
parent
1062b4fef6
commit
060557608c
|
@ -41,11 +41,6 @@
|
||||||
<artifactId>guava</artifactId>
|
<artifactId>guava</artifactId>
|
||||||
<version>${guava.version}</version>
|
<version>${guava.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-databind</artifactId>
|
|
||||||
<version>${jackson.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.platform</groupId>
|
<groupId>org.junit.platform</groupId>
|
||||||
<artifactId>junit-platform-commons</artifactId>
|
<artifactId>junit-platform-commons</artifactId>
|
||||||
|
@ -78,7 +73,6 @@
|
||||||
<commons-codec.version>1.11</commons-codec.version>
|
<commons-codec.version>1.11</commons-codec.version>
|
||||||
<commons-math3.version>3.6.1</commons-math3.version>
|
<commons-math3.version>3.6.1</commons-math3.version>
|
||||||
<guava.version>28.1-jre</guava.version>
|
<guava.version>28.1-jre</guava.version>
|
||||||
<jackson.version>2.10.2</jackson.version>
|
|
||||||
<junit.platform.version>1.6.0</junit.platform.version>
|
<junit.platform.version>1.6.0</junit.platform.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
package com.baeldung.algorithms.boruvka;
|
|
||||||
|
|
||||||
public class BoruvkaMST {
|
|
||||||
|
|
||||||
private static Tree mst = new Tree();
|
|
||||||
private static int totalWeight;
|
|
||||||
|
|
||||||
public BoruvkaMST(Graph graph) {
|
|
||||||
DisjointSet dSet = new DisjointSet(graph.getNodes());
|
|
||||||
|
|
||||||
// repeat at most log N times or until we have N-1 edges
|
|
||||||
for (int t = 1; t < graph.getNodes() && mst.getEdgeCount() < graph.getNodes() - 1; t = t + t) {
|
|
||||||
|
|
||||||
// foreach tree in forest, find closest edge
|
|
||||||
Edge[] closestEdgeArray = new Edge[graph.getNodes()];
|
|
||||||
for (Edge edge : graph.getAllEdges()) {
|
|
||||||
int first = edge.getFirst();
|
|
||||||
int second = edge.getSecond();
|
|
||||||
int firstParent = dSet.getParent(first);
|
|
||||||
int secondParent = dSet.getParent(second);
|
|
||||||
if (firstParent == secondParent) {
|
|
||||||
continue; // same tree
|
|
||||||
}
|
|
||||||
if (closestEdgeArray[firstParent] == null || edge.getWeight() < closestEdgeArray[firstParent].getWeight()) {
|
|
||||||
closestEdgeArray[firstParent] = edge;
|
|
||||||
}
|
|
||||||
if (closestEdgeArray[secondParent] == null || edge.getWeight() < closestEdgeArray[secondParent].getWeight()) {
|
|
||||||
closestEdgeArray[secondParent] = edge;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add newly discovered edges to MST
|
|
||||||
for (int i = 0; i < graph.getNodes(); i++) {
|
|
||||||
Edge edge = closestEdgeArray[i];
|
|
||||||
if (edge != null) {
|
|
||||||
int first = edge.getFirst();
|
|
||||||
int second = edge.getSecond();
|
|
||||||
// don't add the same edge twice
|
|
||||||
if (dSet.getParent(first) != dSet.getParent(second)) {
|
|
||||||
mst.addEdge(edge);
|
|
||||||
totalWeight += edge.getWeight();
|
|
||||||
dSet.union(first, second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterable<Edge> getMST() {
|
|
||||||
return mst;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTotalWeight() {
|
|
||||||
return totalWeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return "MST: " + mst.toString() + " | Total Weight: " + totalWeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
package com.baeldung.algorithms.boruvka;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class DisjointSet {
|
|
||||||
|
|
||||||
private int[] nodeParents;
|
|
||||||
private int[] nodeRanks;
|
|
||||||
|
|
||||||
public DisjointSet(int n) {
|
|
||||||
nodeParents = new int[n];
|
|
||||||
nodeRanks = new int[n];
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
nodeParents[i] = i;
|
|
||||||
nodeRanks[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getParent(int node) {
|
|
||||||
while (node != nodeParents[node]) {
|
|
||||||
node = nodeParents[node];
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void union(int node1, int node2) {
|
|
||||||
int node1Parent = getParent(node1);
|
|
||||||
int node2Parent = getParent(node2);
|
|
||||||
if (node1Parent == node2Parent) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodeRanks[node1Parent] < nodeRanks[node2Parent]) {
|
|
||||||
nodeParents[node1Parent] = node2Parent;
|
|
||||||
}
|
|
||||||
else if (nodeRanks[node1Parent] > nodeRanks[node2Parent]) {
|
|
||||||
nodeParents[node2Parent] = node1Parent;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nodeParents[node2Parent] = node1Parent;
|
|
||||||
nodeRanks[node1Parent]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return "Parent: " + Arrays.toString(nodeParents) + "Rank: " + Arrays.toString(nodeRanks);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
package com.baeldung.algorithms.boruvka;
|
|
||||||
|
|
||||||
public class Edge {
|
|
||||||
|
|
||||||
private final int first;
|
|
||||||
private final int second;
|
|
||||||
private final int weight;
|
|
||||||
|
|
||||||
public Edge(int first, int second, int weight) {
|
|
||||||
this.first = first;
|
|
||||||
this.second = second;
|
|
||||||
this.weight = weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getWeight() {
|
|
||||||
return weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFirst() {
|
|
||||||
return first;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSecond() {
|
|
||||||
return second;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOtherNode(int firstNode) {
|
|
||||||
int secondNode = 0;
|
|
||||||
if (firstNode == first)
|
|
||||||
secondNode = second;
|
|
||||||
else if (firstNode == second)
|
|
||||||
secondNode = first;
|
|
||||||
return secondNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return String.format("%d-%d %d", first, second, weight);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
package com.baeldung.algorithms.boruvka;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParseException;
|
|
||||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
|
||||||
|
|
||||||
public class Graph {
|
|
||||||
|
|
||||||
private int nodes;
|
|
||||||
private int edges;
|
|
||||||
private Tree[] trees;
|
|
||||||
|
|
||||||
public Graph(Input jsonGraph) throws JsonParseException, JsonMappingException, IOException {
|
|
||||||
nodes = jsonGraph.getNodes();
|
|
||||||
trees = (Tree[]) new Tree[nodes];
|
|
||||||
for (int i = 0; i < nodes; i++) {
|
|
||||||
trees[i] = new Tree();
|
|
||||||
}
|
|
||||||
|
|
||||||
int edgesFromInput = jsonGraph.getEdges();
|
|
||||||
for (int i = 0; i < edgesFromInput; i++) {
|
|
||||||
int first = jsonGraph.getEdgeList()
|
|
||||||
.get(i)
|
|
||||||
.getFirst();
|
|
||||||
int second = jsonGraph.getEdgeList()
|
|
||||||
.get(i)
|
|
||||||
.getSecond();
|
|
||||||
int weight = jsonGraph.getEdgeList()
|
|
||||||
.get(i)
|
|
||||||
.getWeight();
|
|
||||||
Edge edge = new Edge(first, second, weight);
|
|
||||||
|
|
||||||
trees[first].addEdge(edge);
|
|
||||||
trees[second].addEdge(edge);
|
|
||||||
edges++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNodes() {
|
|
||||||
return nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getEdges() {
|
|
||||||
return edges;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterable<Edge> iterableTree(int i) {
|
|
||||||
return trees[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterable<Edge> getAllEdges() {
|
|
||||||
Iterable<Edge> list = new Tree();
|
|
||||||
for (int i = 0; i < nodes; i++) {
|
|
||||||
for (Edge edge : iterableTree(i)) {
|
|
||||||
if (edge.getOtherNode(i) > i) {
|
|
||||||
((Tree) list).addEdge(edge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
package com.baeldung.algorithms.boruvka;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class Input {
|
|
||||||
private int nodes;
|
|
||||||
private int edges;
|
|
||||||
private List<E> edgeList;
|
|
||||||
|
|
||||||
public int getNodes() {
|
|
||||||
return nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNodes(int nodes) {
|
|
||||||
this.nodes = nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getEdges() {
|
|
||||||
return edges;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEdges(int edges) {
|
|
||||||
this.edges = edges;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<E> getEdgeList() {
|
|
||||||
return edgeList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEdgeList(List<E> edgeList) {
|
|
||||||
this.edgeList = edgeList;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class E {
|
|
||||||
private int first;
|
|
||||||
private int second;
|
|
||||||
private int weight;
|
|
||||||
|
|
||||||
public int getFirst() {
|
|
||||||
return first;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFirst(int first) {
|
|
||||||
this.first = first;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSecond() {
|
|
||||||
return second;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSecond(int second) {
|
|
||||||
this.second = second;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWeight() {
|
|
||||||
return weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWeight(int weight) {
|
|
||||||
this.weight = weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
package com.baeldung.algorithms.boruvka;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
public class Tree implements Iterable<Edge> {
|
|
||||||
private Node root;
|
|
||||||
private int edgeCount;
|
|
||||||
|
|
||||||
private static class Node {
|
|
||||||
private Edge edge;
|
|
||||||
private Node next;
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
String nextStr = next != null ? next.toString() : "";
|
|
||||||
return edge.toString() + " | " + nextStr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Tree() {
|
|
||||||
root = null;
|
|
||||||
edgeCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getEdgeCount() {
|
|
||||||
return edgeCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addEdge(Edge edge) {
|
|
||||||
Node oldRoot = root;
|
|
||||||
root = new Node();
|
|
||||||
root.edge = edge;
|
|
||||||
root.next = oldRoot;
|
|
||||||
edgeCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
String rootStr = root != null ? root.toString() : "";
|
|
||||||
return "Tree: " + rootStr + "Size: " + edgeCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterator<Edge> iterator() {
|
|
||||||
return new LinkedIterator(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class LinkedIterator implements Iterator<Edge> {
|
|
||||||
private Node current;
|
|
||||||
|
|
||||||
public LinkedIterator(Node root) {
|
|
||||||
current = root;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasNext() {
|
|
||||||
return current != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Edge next() {
|
|
||||||
Edge edge = current.edge;
|
|
||||||
current = current.next;
|
|
||||||
return edge;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
package com.baeldung.algorithms.boruvka;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParseException;
|
|
||||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
|
|
||||||
public class BoruvkaUnitTest {
|
|
||||||
|
|
||||||
private Input input;
|
|
||||||
private static String INPUT_JSON = "/input.json";
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void convertInputJsonToObject() throws JsonParseException, JsonMappingException, IOException {
|
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
|
||||||
StringBuilder jsonStr = new StringBuilder();
|
|
||||||
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(BoruvkaMST.class.getResourceAsStream(INPUT_JSON)))) {
|
|
||||||
String line;
|
|
||||||
while ((line = bufferedReader.readLine()) != null) {
|
|
||||||
jsonStr.append(line)
|
|
||||||
.append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
input = mapper.readValue(jsonStr.toString(), Input.class);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void givenInputGraph_whenBoruvkaPerformed_thenMinimumSpanningTree() throws JsonParseException, JsonMappingException, IOException {
|
|
||||||
Graph graph = new Graph(input);
|
|
||||||
BoruvkaMST boruvkaMST = new BoruvkaMST(graph);
|
|
||||||
|
|
||||||
Tree mst = (Tree) boruvkaMST.getMST();
|
|
||||||
|
|
||||||
assertEquals(30, boruvkaMST.getTotalWeight());
|
|
||||||
assertEquals(4, mst.getEdgeCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -11,5 +11,17 @@
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>${guava.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<guava.version>28.1-jre</guava.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
package com.baeldung.algorithms.boruvka;
|
||||||
|
|
||||||
|
import com.google.common.graph.EndpointPair;
|
||||||
|
import com.google.common.graph.MutableValueGraph;
|
||||||
|
import com.google.common.graph.ValueGraphBuilder;
|
||||||
|
|
||||||
|
public class BoruvkaMST {
|
||||||
|
|
||||||
|
private static MutableValueGraph<Integer, Integer> mst = ValueGraphBuilder.undirected()
|
||||||
|
.build();
|
||||||
|
private static int totalWeight;
|
||||||
|
|
||||||
|
public BoruvkaMST(MutableValueGraph<Integer, Integer> graph) {
|
||||||
|
|
||||||
|
int size = graph.nodes().size();
|
||||||
|
|
||||||
|
UnionFind uf = new UnionFind(size);
|
||||||
|
|
||||||
|
// repeat at most log N times or until we have N-1 edges
|
||||||
|
for (int t = 1; t < size && mst.edges().size() < size - 1; t = t + t) {
|
||||||
|
|
||||||
|
EndpointPair<Integer>[] closestEdgeArray = new EndpointPair[size];
|
||||||
|
|
||||||
|
// foreach tree in graph, find closest edge
|
||||||
|
for (EndpointPair<Integer> edge : graph.edges()) {
|
||||||
|
int u = edge.nodeU();
|
||||||
|
int v = edge.nodeV();
|
||||||
|
int uParent = uf.find(u);
|
||||||
|
int vParent = uf.find(v);
|
||||||
|
if (uParent == vParent) {
|
||||||
|
continue; // same tree
|
||||||
|
}
|
||||||
|
|
||||||
|
int weight = graph.edgeValueOrDefault(u, v, 0);
|
||||||
|
|
||||||
|
if (closestEdgeArray[uParent] == null) {
|
||||||
|
closestEdgeArray[uParent] = edge;
|
||||||
|
}
|
||||||
|
if (closestEdgeArray[vParent] == null) {
|
||||||
|
closestEdgeArray[vParent] = edge;
|
||||||
|
}
|
||||||
|
|
||||||
|
int uParentWeight = graph.edgeValueOrDefault(closestEdgeArray[uParent].nodeU(), closestEdgeArray[uParent].nodeV(), 0);
|
||||||
|
int vParentWeight = graph.edgeValueOrDefault(closestEdgeArray[vParent].nodeU(), closestEdgeArray[vParent].nodeV(), 0);
|
||||||
|
|
||||||
|
if (weight < uParentWeight) {
|
||||||
|
closestEdgeArray[uParent] = edge;
|
||||||
|
}
|
||||||
|
if (weight < vParentWeight) {
|
||||||
|
closestEdgeArray[vParent] = edge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add newly discovered edges to MST
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
EndpointPair<Integer> edge = closestEdgeArray[i];
|
||||||
|
if (edge != null) {
|
||||||
|
int u = edge.nodeU();
|
||||||
|
int v = edge.nodeV();
|
||||||
|
int weight = graph.edgeValueOrDefault(u, v, 0);
|
||||||
|
// don't add the same edge twice
|
||||||
|
if (uf.find(u) != uf.find(v)) {
|
||||||
|
mst.putEdgeValue(u, v, weight);
|
||||||
|
totalWeight += weight;
|
||||||
|
uf.union(u, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableValueGraph<Integer, Integer> getMST() {
|
||||||
|
return mst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotalWeight() {
|
||||||
|
return totalWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "MST: " + mst.toString() + " | Total Weight: " + totalWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.baeldung.algorithms.boruvka;
|
||||||
|
|
||||||
|
public class UnionFind {
|
||||||
|
private int[] parents;
|
||||||
|
private int[] ranks;
|
||||||
|
|
||||||
|
public UnionFind(int n) {
|
||||||
|
parents = new int[n];
|
||||||
|
ranks = new int[n];
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
parents[i] = i;
|
||||||
|
ranks[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int find(int u) {
|
||||||
|
while (u != parents[u]) {
|
||||||
|
u = parents[u];
|
||||||
|
}
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void union(int u, int v) {
|
||||||
|
int uParent = find(u);
|
||||||
|
int vParent = find(v);
|
||||||
|
if (uParent == vParent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ranks[uParent] < ranks[vParent]) {
|
||||||
|
parents[uParent] = vParent;
|
||||||
|
} else if (ranks[uParent] > ranks[vParent]) {
|
||||||
|
parents[vParent] = uParent;
|
||||||
|
} else {
|
||||||
|
parents[vParent] = uParent;
|
||||||
|
ranks[uParent]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.baeldung.algorithms.boruvka;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.google.common.graph.MutableValueGraph;
|
||||||
|
import com.google.common.graph.ValueGraphBuilder;
|
||||||
|
|
||||||
|
public class BoruvkaUnitTest {
|
||||||
|
|
||||||
|
private MutableValueGraph<Integer, Integer> graph;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
graph = ValueGraphBuilder.undirected()
|
||||||
|
.build();
|
||||||
|
graph.putEdgeValue(0, 1, 8);
|
||||||
|
graph.putEdgeValue(0, 2, 5);
|
||||||
|
graph.putEdgeValue(1, 2, 9);
|
||||||
|
graph.putEdgeValue(1, 3, 11);
|
||||||
|
graph.putEdgeValue(2, 3, 15);
|
||||||
|
graph.putEdgeValue(2, 4, 10);
|
||||||
|
graph.putEdgeValue(3, 4, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenInputGraph_whenBoruvkaPerformed_thenMinimumSpanningTree() {
|
||||||
|
BoruvkaMST boruvkaMST = new BoruvkaMST(graph);
|
||||||
|
MutableValueGraph<Integer, Integer> mst = boruvkaMST.getMST();
|
||||||
|
|
||||||
|
assertEquals(30, boruvkaMST.getTotalWeight());
|
||||||
|
assertEquals(4, mst.edges().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue