// Stephanie's class notes. // sorely missing comments and docstrings. sorry. // Weighted Graph implemented with adjacency list // Note: I have implemented the graph as an undirected graph. import java.util.*; public class Graph1 { private ArrayList nodes; public enum Color { RED, BLUE, NONE }; private static class EdgeTo { private int weight; private GraphNode node; public EdgeTo( int weight, GraphNode node ) { this.weight = weight; this.node = node; } } public static class GraphNode { private ArrayList neighbors; String label; boolean marked; Color color; int cost; public GraphNode() { this.neighbors = new ArrayList(); this.label = ""; this.marked = false; this.color = Color.NONE; this.cost = 0; } public GraphNode(String label) { this.neighbors = new ArrayList(); this.label = label; this.marked = false; this.cost = 0; } // make a directed connection from this node to the other node public void connectTo( int weight, GraphNode other ) { this.neighbors.add( new EdgeTo( weight, other ) ); } public String toString() { String ret = this.label; if (this.cost == Integer.MAX_VALUE) ret += "(max):"; else ret += "(" + this.cost + "):"; for (EdgeTo n: this.neighbors) ret += " " + n.node.label; return ret; } } // end class GraphNode public Graph1() { nodes = new ArrayList(); } public void connect( GraphNode fromNode, GraphNode toNode, int weight ) { if (! this.nodes.contains( fromNode )) this.nodes.add( fromNode ); if (! this.nodes.contains( toNode )) this.nodes.add( toNode ); fromNode.connectTo( weight, toNode ); toNode.connectTo( weight, fromNode ); } public void printAll() { for (GraphNode n: nodes) System.out.println( n ); } public void generalTraversalPrint(GraphNode n0) { // unmark all nodes for (GraphNode n: nodes) n.marked = false; ArrayDeque nbs = new ArrayDeque(); nbs.add( n0 ); while (!nbs.isEmpty()) { GraphNode n = nbs.remove(); n.marked = true; System.out.println( n ); for (EdgeTo pe: n.neighbors) { GraphNode p = pe.node; if (!p.marked && !nbs.contains(p)) nbs.add( p ); } } } /* Make a comparator that compares GraphNodes according to their costs. */ private class MinGraphNodeComparator implements Comparator { public int compare( GraphNode a, GraphNode b ) { if (a.cost < b.cost) return -1; else if (a.cost == b.cost) return 0; else return 1; } } /* Given: a graph G and starting vertex v0 in G Initialize all vertices in G to be unmarked and have infinite cost Create a priority queue, q, that orders vertices by lowest cost Set the cost of v0 to 0 and add it to q while q is not empty: let v be the vertex in q with lowest cost remove v from q mark v as visited for each vertex w that neighbors v: if w is not marked and v.cost + vw_edge_weight < w.cost: w.cost = v.cost + vw_edge_weight add w to q Output: the cost of each vertex v in G is the shortest distance from v0 to v. */ public void shortestPath(GraphNode v0) { //unmark all nodes and set their cost to be high int high_cost = Integer.MAX_VALUE; for (GraphNode n: nodes) { n.marked = false; n.cost = high_cost; } PriorityQueue q = new PriorityQueue(this.nodes.size(), new MinGraphNodeComparator()); v0.cost = 0; q.add( v0 ); while (!q.isEmpty()) { GraphNode v = q.remove(); v.marked = true; System.out.println( "Looking at " + v.label + " (now marked)" ); for (EdgeTo vw: v.neighbors) { GraphNode w = vw.node; int edge_cost= vw.weight; System.out.println( " " + w.label + " has current distance " + w.cost ); if (!w.marked && v.cost + edge_cost < w.cost) { w.cost = v.cost + edge_cost; System.out.println( " putting " + w.label + " into the q with distance " + w.cost ); q.remove( w ); // if it is already there, but with a different cost, then remove it q.add( w ); System.out.println( " the queue now looks like this: " + q ); } } } } private static class IntComparator implements Comparator { public int compare( Integer i1, Integer i2 ) { return i1.compareTo(i2); } } public static void main( String[] args ) { // Figure out how to use Java's built in PQ // It is by default a min-queue. // PriorityQueue q = new PriorityQueue(10, new IntComparator()); // q.add( 10 ); // q.add( 20 ); // System.out.println( q ); Graph1 g = new Graph1(); GraphNode n1 = new GraphNode( "n1" ); GraphNode n2 = new GraphNode( "n2" ); GraphNode n3 = new GraphNode( "n3" ); GraphNode n4 = new GraphNode( "n4" ); g.connect( n1, n2, 10 ); g.connect( n2, n3, 2 ); g.connect( n3, n4, 5 ); g.connect( n2, n4, 10 ); g.printAll(); g.shortestPath(n1); for (GraphNode n: g.nodes) System.out.println( n.label + " is " + n.cost + " away from n1" ); } }