diff --git a/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/prim/Edge.java b/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/prim/Edge.java new file mode 100644 index 0000000000..52ec4ef534 --- /dev/null +++ b/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/prim/Edge.java @@ -0,0 +1,36 @@ +package com.baeldung.algorithms.prim; + +public class Edge { + + private int weight; + private boolean isIncluded = false; + private boolean isPrinted = false; + + public Edge(int weight) { + this.weight = weight; + } + + public int getWeight() { + return weight; + } + + public void setWeight(int weight) { + this.weight = weight; + } + + public boolean isIncluded() { + return isIncluded; + } + + public void setIncluded(boolean included) { + isIncluded = included; + } + + public boolean isPrinted() { + return isPrinted; + } + + public void setPrinted(boolean printed) { + isPrinted = printed; + } +} diff --git a/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/prim/Prim.java b/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/prim/Prim.java new file mode 100644 index 0000000000..365dca6b62 --- /dev/null +++ b/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/prim/Prim.java @@ -0,0 +1,73 @@ +package com.baeldung.algorithms.prim; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.math3.util.Pair; + +public class Prim { + + private List graph; + + public Prim(List graph){ + this.graph = graph; + } + + public void run(){ + if (graph.size() > 0){ + graph.get(0).setVisited(true); + } + while (isDisconnected()){ + Edge nextMinimum = new Edge(Integer.MAX_VALUE); + Vertex nextVertex = graph.get(0); + for (Vertex vertex : graph){ + if (vertex.isVisited()){ + Pair candidate = vertex.nextMinimum(); + if (candidate.getValue().getWeight() < nextMinimum.getWeight()){ + nextMinimum = candidate.getValue(); + nextVertex = candidate.getKey(); + } + } + } + nextMinimum.setIncluded(true); + nextVertex.setVisited(true); + } + } + + private boolean isDisconnected(){ + for (Vertex vertex : graph){ + if (!vertex.isVisited()){ + return true; + } + } + return false; + } + + public String originalGraphToString(){ + StringBuilder sb = new StringBuilder(); + for (Vertex vertex : graph){ + sb.append(vertex.originalToString()); + } + return sb.toString(); + } + + public void resetPrintHistory(){ + for (Vertex vertex : graph){ + Iterator> it = vertex.getEdges().entrySet().iterator(); + while (it.hasNext()) { + Map.Entry pair = it.next(); + pair.getValue().setPrinted(false); + } + } + } + + public String minimumSpanningTreeToString(){ + StringBuilder sb = new StringBuilder(); + for (Vertex vertex : graph){ + sb.append(vertex.includedToString()); + } + return sb.toString(); + } + +} diff --git a/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/prim/Vertex.java b/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/prim/Vertex.java new file mode 100644 index 0000000000..982d9331bc --- /dev/null +++ b/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/prim/Vertex.java @@ -0,0 +1,106 @@ +package com.baeldung.algorithms.prim; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.math3.util.Pair; + +public class Vertex { + + private String label = null; + private Map edges = new HashMap<>(); + private boolean isVisited = false; + + public Vertex(String label){ + this.label = label; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public Map getEdges() { + return edges; + } + + public void addEdge(Vertex vertex, Edge edge){ + if (this.edges.containsKey(vertex)){ + if (edge.getWeight() < this.edges.get(vertex).getWeight()){ + this.edges.replace(vertex, edge); + } + } else { + this.edges.put(vertex, edge); + } + } + + public boolean isVisited() { + return isVisited; + } + + public void setVisited(boolean visited) { + isVisited = visited; + } + + public Pair nextMinimum(){ + Edge nextMinimum = new Edge(Integer.MAX_VALUE); + Vertex nextVertex = this; + Iterator> it = edges.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry pair = it.next(); + if (!pair.getKey().isVisited()){ + if (!pair.getValue().isIncluded()) { + if (pair.getValue().getWeight() < nextMinimum.getWeight()) { + nextMinimum = pair.getValue(); + nextVertex = pair.getKey(); + } + } + } + } + return new Pair<>(nextVertex, nextMinimum); + } + + public String originalToString(){ + StringBuilder sb = new StringBuilder(); + Iterator> it = edges.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry pair = it.next(); + if (!pair.getValue().isPrinted()) { + sb.append(getLabel()); + sb.append(" --- "); + sb.append(pair.getValue().getWeight()); + sb.append(" --- "); + sb.append(pair.getKey().getLabel()); + sb.append("\n"); + pair.getValue().setPrinted(true); + } + } + return sb.toString(); + } + + public String includedToString(){ + StringBuilder sb = new StringBuilder(); + if (isVisited()) { + Iterator> it = edges.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry pair = it.next(); + if (pair.getValue().isIncluded()) { + if (!pair.getValue().isPrinted()) { + sb.append(getLabel()); + sb.append(" --- "); + sb.append(pair.getValue().getWeight()); + sb.append(" --- "); + sb.append(pair.getKey().getLabel()); + sb.append("\n"); + pair.getValue().setPrinted(true); + } + } + } + } + return sb.toString(); + } +} diff --git a/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/prim/PrimUnitTest.java b/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/prim/PrimUnitTest.java new file mode 100644 index 0000000000..41e53fc9f2 --- /dev/null +++ b/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/prim/PrimUnitTest.java @@ -0,0 +1,54 @@ +package com.baeldung.algorithms.prim; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +public class PrimUnitTest { + + @Test + public void givenAGraph_whenPrimRuns_thenPrintMST() { + Prim prim = new Prim(createGraph()); + System.out.println(prim.originalGraphToString()); + System.out.println("----------------"); + prim.run(); + System.out.println(); + prim.resetPrintHistory(); + System.out.println(prim.minimumSpanningTreeToString()); + } + + public static List createGraph() { + List graph = new ArrayList<>(); + Vertex a = new Vertex("A"); + Vertex b = new Vertex("B"); + Vertex c = new Vertex("C"); + Vertex d = new Vertex("D"); + Vertex e = new Vertex("E"); + Edge ab = new Edge(2); + a.addEdge(b, ab); + b.addEdge(a, ab); + Edge ac = new Edge(3); + a.addEdge(c, ac); + c.addEdge(a, ac); + Edge bc = new Edge(2); + b.addEdge(c, bc); + c.addEdge(b, bc); + Edge be = new Edge(5); + b.addEdge(e, be); + e.addEdge(b, be); + Edge cd = new Edge(1); + c.addEdge(d, cd); + d.addEdge(c, cd); + Edge ce = new Edge(1); + c.addEdge(e, ce); + e.addEdge(c, ce); + graph.add(a); + graph.add(b); + graph.add(c); + graph.add(d); + graph.add(e); + return graph; + } + +}