diff --git a/Others/Dijkstra.java b/Others/Dijkstra.java new file mode 100644 index 00000000..b3df65bf --- /dev/null +++ b/Others/Dijkstra.java @@ -0,0 +1,171 @@ +package Others; + + +/** + * Dijkstra's algorithm,is a graph search algorithm that solves the single-source + * shortest path problem for a graph with nonnegative edge path costs, producing + * a shortest path tree. + * + * NOTE: The inputs to Dijkstra's algorithm are a directed and weighted graph consisting + * of 2 or more nodes, generally represented by an adjacency matrix or list, and a start node. + * + * Original source of code: https://rosettacode.org/wiki/Dijkstra%27s_algorithm#Java + * Also most of the comments are from RosettaCode. + * + */ +//import java.io.*; +import java.util.*; +public class Dijkstra { + private static final Graph.Edge[] GRAPH = { + new Graph.Edge("a", "b", 7), //Distance from node "a" to node "b" is 7. In the current Graph there is no way to move the other way (e,g, from "b" to "a"), a new edge would be needed for that + new Graph.Edge("a", "c", 9), + new Graph.Edge("a", "f", 14), + new Graph.Edge("b", "c", 10), + new Graph.Edge("b", "d", 15), + new Graph.Edge("c", "d", 11), + new Graph.Edge("c", "f", 2), + new Graph.Edge("d", "e", 6), + new Graph.Edge("e", "f", 9), + }; + private static final String START = "a"; + private static final String END = "e"; + + /** + * main function + * Will run the code with "GRAPH" that was defined above. + */ + public static void main(String[] args) { + Graph g = new Graph(GRAPH); + g.dijkstra(START); + g.printPath(END); + //g.printAllPaths(); + } +} + +class Graph { + private final Map graph; // mapping of vertex names to Vertex objects, built from a set of Edges + + /** One edge of the graph (only used by Graph constructor) */ + public static class Edge { + public final String v1, v2; + public final int dist; + public Edge(String v1, String v2, int dist) { + this.v1 = v1; + this.v2 = v2; + this.dist = dist; + } + } + + /** One vertex of the graph, complete with mappings to neighbouring vertices */ + public static class Vertex implements Comparable { + public final String name; + public int dist = Integer.MAX_VALUE; // MAX_VALUE assumed to be infinity + public Vertex previous = null; + public final Map neighbours = new HashMap<>(); + + public Vertex(String name) { + this.name = name; + } + + private void printPath() { + if (this == this.previous) { + System.out.printf("%s", this.name); + } + else if (this.previous == null) { + System.out.printf("%s(unreached)", this.name); + } + else { + this.previous.printPath(); + System.out.printf(" -> %s(%d)", this.name, this.dist); + } + } + + public int compareTo(Vertex other) { + if (dist == other.dist) + return name.compareTo(other.name); + + return Integer.compare(dist, other.dist); + } + + @Override public String toString() { + return "(" + name + ", " + dist + ")"; + } +} + + /** Builds a graph from a set of edges */ + public Graph(Edge[] edges) { + graph = new HashMap<>(edges.length); + + //one pass to find all vertices + for (Edge e : edges) { + if (!graph.containsKey(e.v1)) graph.put(e.v1, new Vertex(e.v1)); + if (!graph.containsKey(e.v2)) graph.put(e.v2, new Vertex(e.v2)); + } + + //another pass to set neighbouring vertices + for (Edge e : edges) { + graph.get(e.v1).neighbours.put(graph.get(e.v2), e.dist); + //graph.get(e.v2).neighbours.put(graph.get(e.v1), e.dist); // also do this for an undirected graph + } + } + + /** Runs dijkstra using a specified source vertex */ + public void dijkstra(String startName) { + if (!graph.containsKey(startName)) { + System.err.printf("Graph doesn't contain start vertex \"%s\"\n", startName); + return; + } + final Vertex source = graph.get(startName); + NavigableSet q = new TreeSet<>(); + + // set-up vertices + for (Vertex v : graph.values()) { + v.previous = v == source ? source : null; + v.dist = v == source ? 0 : Integer.MAX_VALUE; + q.add(v); + } + + dijkstra(q); + } + + /** Implementation of dijkstra's algorithm using a binary heap. */ + private void dijkstra(final NavigableSet q) { + Vertex u, v; + while (!q.isEmpty()) { + + u = q.pollFirst(); // vertex with shortest distance (first iteration will return source) + if (u.dist == Integer.MAX_VALUE) break; // we can ignore u (and any other remaining vertices) since they are unreachable + + //look at distances to each neighbour + for (Map.Entry a : u.neighbours.entrySet()) { + v = a.getKey(); //the neighbour in this iteration + + final int alternateDist = u.dist + a.getValue(); + if (alternateDist < v.dist) { // shorter path to neighbour found + q.remove(v); + v.dist = alternateDist; + v.previous = u; + q.add(v); + } + } + } + } + + /** Prints a path from the source to the specified vertex */ + public void printPath(String endName) { + if (!graph.containsKey(endName)) { + System.err.printf("Graph doesn't contain end vertex \"%s\"\n", endName); + return; + } + + graph.get(endName).printPath(); + System.out.println(); + } + /** Prints the path from the source to every vertex (output order is not guaranteed) */ + public void printAllPaths() { + for (Vertex v : graph.values()) { + v.printPath(); + System.out.println(); + } + } +} diff --git a/SkylineProblem/SkylineProblem.java b/SkylineProblem/SkylineProblem.java index a0b70631..121116e1 100644 --- a/SkylineProblem/SkylineProblem.java +++ b/SkylineProblem/SkylineProblem.java @@ -1,3 +1,9 @@ +/** + * Given n rectangular buildings in a 2-dimensional city, computes the skyline of these buildings, + * eliminating hidden lines. The main task is to view buildings from a side and remove all sections + * that are not visible. + * Source for explanation: https://www.geeksforgeeks.org/the-skyline-problem-using-divide-and-conquer-algorithm/ + */ import java.util.ArrayList; import java.util.Iterator; import java.util.Scanner;