import java.util.ArrayList; import java.util.PriorityQueue; /** * Implementation of a graph using an adjacency list. * * @author geoffreytowell * * @param */ public class Graph { /** * The one, and only, list of nodes */ ArrayList> adjList; public Graph() { adjList = new ArrayList<>(); } public void addNode(Node n) { adjList.add(n); } /** * * @param args * flags -basic == some simple tests of the graph * -dijk == run dijkstra's shortest path algorithm * this is the default if no arguement is supplied. */ public static void main(String[] args) { Graph g = new Graph<>(); Node a = new Node('a'); Node b = new Node('b'); Node c = new Node('c'); Node d = new Node('d'); Node e = new Node('e'); g.addNode(a); g.addNode(b); g.addNode(c); g.addNode(d); g.addNode(e); a.addEdgeTo(b, "ab", 1); a.addEdgeTo(c, "ac", 3); a.addEdgeTo(d, "ad", 5); b.addEdgeTo(c, "bc", 1); b.addEdgeTo(d, "bd", 3); b.addEdgeTo(a, "ba", 1); c.addEdgeTo(e, "ce", 1); d.addEdgeTo(e, "de", 1); g.showGraph(); if (args.length > 0 && args[1].equals("-basic")) { System.out.println("Reachable from " + a); g.reachable(a); System.out.println("Reachable from " + b); g.reachable(b); System.out.println("Reachable from " + c); g.reachable(c); System.out.println("Path from A to E"); g.findPath1(a, e); System.out.println("Done"); } if (args.length == 0 || args[1].equals("-dijk")) { System.out.println("\n\nDijkstra's shortest path from Node A"); g.djk(a); } } /** * Drop a very simple print representation of the graph */ public void showGraph() { for (Node node : adjList) { System.out.println(node); for (Edge ed : node.getEdges()) { System.out.println(" " + ed); } } } /** * Print a list of all nodes reachable from a given node * @param n */ public void reachable(Node n) { ArrayList> r = new ArrayList<>(); iReachable(n, r); for (Node nn : r) System.out.println(nn); } /** * Recursive helper function for reachable * * @param n * @param rble */ private void iReachable(Node n, ArrayList> rble) { if (rble.contains(n)) return; rble.add(n); for (Edge e : n.getEdges()) iReachable(e.getToo(), rble); } /** * Print a path between two nodes. This is simply the first path found. * @param from * @param too */ public void findPath1(Nodefrom, Node too) { ArrayList> r = new ArrayList<>(); boolean b = iFindPath1(from, too, r); if (!b) System.out.println("No Path"); else System.out.println(from); } /** * Recursive helper fucntion for finding a path. * @param current * @param dest * @param rble * @return */ private boolean iFindPath1(Node current, Nodedest, ArrayList> rble) { if (current == dest) return true; if (rble.contains(current)) return false; rble.add(current); for (Edge e : current.getEdges()) { boolean b = iFindPath1(e.getToo(), dest, rble); if (b) { System.out.println(e.getToo()); return true; } } return false; } /** * Implement Dijkstra's shortest path algorithm (1956) * @param node */ public void djk(Node node) { PriorityQueue> pq = new PriorityQueue<>(); for (Node n : adjList) { n.reset(); } node.setCost(0); pq.add(node); while (pq.size() > 0) { Node current = pq.poll(); current.setVisited(true); //System.out.println("Working with " + current + " " + current.getCost() ); for (Edge ed : current.getEdges()) { if (!ed.getToo().getVisited()) { int cc = current.getCost() + ed.getCost(); if (cc < ed.getToo().getCost()) { if (pq.contains(ed.getToo())) { // To update the java priorityqueue, you need to remove then add pq.remove(ed.getToo()); } // Update the node with new cost and path ed.getToo().setCost(cc); ed.getToo().setPriorEdges(current.getPriorEdges()); ed.getToo().addPriorEdge(ed); // add the node into the priority queue pq.add(ed.getToo()); } } } } for (Node n : adjList) { System.out.println(n.toString() + " cost:" + n.getCost() + " Path:" + n.getPriorEdges()); } } }