diff --git a/graph/BFS.java b/graph/BFS.java new file mode 100644 index 0000000..fe013b1 --- /dev/null +++ b/graph/BFS.java @@ -0,0 +1,131 @@ + +//gioel + +package graph; + + +import arraylist.ArrayIndexList; +import arraylist.IndexList; +import position.NodePositionList; +import position.PositionList; + +import java.security.InvalidKeyException; + +public abstract class BFS { + protected Graph graph; + protected Vertex start; + protected I info; + protected R visitResult; + protected static Object STATUS = new Object(); + protected static Object VISITED = new Object(); + protected static Object UNVISITED = new Object(); + + protected IndexList>> layers; + + public R execute(Graph g, Vertex s, I in) throws InvalidKeyException{ + graph = g; + layers = new ArrayIndexList>>( + graph.numVertices()); + start = s; + info = in; + for (Vertex v : graph.vertices()) + unVisit(v); + for (Edge e : graph.edges()) + unVisit(e); + + setup(); + return finalResult(bfsTraversal(start)); + } + + protected void setup() { + } + + protected R bfsTraversal(Vertex v) throws InvalidKeyException{ + initResult(); + if (!isDone()) + startVisit(v); + + if (!isDone()) { + visit(v); + + layers.add(0, new NodePositionList>()); + layers.get(0).addLast(v); + } + + int i = 0; + while (!layers.get(i).isEmpty()) { + layers.add(i + 1, new NodePositionList>()); + + for (Vertex vertexInLayer : layers.get(i)) { + for (Edge e : graph.incidentEdges(vertexInLayer)) { + if (!isVisited(e)) { + visit(e); + Vertex w = graph.opposite(vertexInLayer, e); + if (!isVisited(w)) { + traverseDiscovery(e, vertexInLayer); + + if (isDone()) + break; + + visit(w); + layers.get(i + 1).addLast(w); + + if (isDone()) + break; + } else { + traverseCross(e, v); + if (isDone()) + break; + } + } + } + + if (!isDone()) + finishVisit(vertexInLayer); + } + + i++; + } + + return result(); + } + + protected void initResult() { + } + + protected void startVisit(Vertex v) { + } + + protected void traverseCross(Edge e, Vertex v) { + } + + protected void traverseDiscovery(Edge e, Vertex v) { + } + + protected void finishVisit(Vertex v) { + } + + protected boolean isDone() { + return false; + } + + protected R result() { + return null; + } + + protected R finalResult(R r) { + return null; + } + + protected void visit(DecorablePosition p) throws InvalidKeyException{ + p.put(STATUS, VISITED); + } + + protected void unVisit(DecorablePosition p) throws InvalidKeyException { + p.put(STATUS, UNVISITED); + } + + protected boolean isVisited(DecorablePosition p) throws InvalidKeyException { + return p.get(STATUS) == VISITED; + } +} diff --git a/graph/ComponentsBFS.java b/graph/ComponentsBFS.java new file mode 100644 index 0000000..864d35a --- /dev/null +++ b/graph/ComponentsBFS.java @@ -0,0 +1,39 @@ +//gioel + +package graph; + +import java.security.InvalidKeyException; + +public class ComponentsBFS extends BFS { + protected Integer compNumber; + protected Object COMPONENT = new Object(); + + protected void setup() { + compNumber = 1; + } + + protected void startVisit(Vertex v) { + try { + v.put(COMPONENT, compNumber); + } + catch (InvalidKeyException e){ + + } + } + + protected Integer finalResult(Integer bfsResult) { + try { + for(Vertex v : graph.vertices()) + if(!isVisited(v)) { + compNumber++; + bfsTraversal(v); + } + + return compNumber; + } + catch (InvalidKeyException e){ + + } + return null; + } +} diff --git a/graph/ComponentsDFS.java b/graph/ComponentsDFS.java new file mode 100644 index 0000000..ac40c97 --- /dev/null +++ b/graph/ComponentsDFS.java @@ -0,0 +1,35 @@ +package graph; + +//begin#fragment CC + +import java.security.InvalidKeyException; + +/** This class extends DFS to compute the connected components of a graph. */ +public class ComponentsDFS extends DFS { + protected Integer compNumber; // Connected component number + protected Object COMPONENT = new Object(); // Connected comp. selector + protected void setup() { compNumber = 1; } + protected void startVisit(Vertex v) { + try{ + v.put(COMPONENT, compNumber); + } + catch (InvalidKeyException e){ + // + } + } + protected Integer finalResult(Integer dfsResult) { + try{ + for (Vertex v : graph.vertices()) // check for any unvisited vertices + if (v.get(STATUS) == UNVISITED) { + compNumber += 1; // we have found another connected component + dfsTraversal(v); // visit all the vertices of this component + } + return compNumber; + } + catch (InvalidKeyException e){ + // + } + return null; + } +} +//end#fragment CC diff --git a/graph/DFS.java b/graph/DFS.java new file mode 100644 index 0000000..bc6e7a4 --- /dev/null +++ b/graph/DFS.java @@ -0,0 +1,106 @@ +package graph; + + +import java.security.InvalidKeyException; + +/** Generic DFS traversal of a graph using the template method pattern. + * Parameterized types: + * V, the type for the elements stored at vertices + * E, the type for the elements stored at edges + * I, the type for the information object passed to the execute method + * R, the type for the result object returned by the DFS + */ +public class DFS { + protected Graph graph; // The graph being traversed + protected Vertex start; // The start vertex for the DFS + protected I info; // Information object passed to DFS + protected R visitResult; // The result of a recursive traversal call + protected static Object STATUS = new Object(); // The status attribute + protected static Object VISITED = new Object(); // Visited value + protected static Object UNVISITED = new Object(); // Unvisited value + + + + /** Execute a depth first search traversal on graph g, starting + * from a start vertex s, passing in an information object (in) */ + public R execute(Graph g, Vertex s, I in) throws InvalidKeyException { + graph = g; + start = s; + info = in; + for(Vertex v: graph.vertices()) unVisit(v); // mark vertices as unvisited + for(Edge e: graph.edges()) unVisit(e); // mark edges as unvisited + setup(); // perform any necessary setup prior to DFS traversal + return finalResult(dfsTraversal(start)); + } + /** Recursive template method for a generic DFS traversal. */ + protected R dfsTraversal(Vertex v) throws InvalidKeyException{ + initResult(); + if (!isDone()) + startVisit(v); + if (!isDone()) { + visit(v); + for (Edge e: graph.incidentEdges(v)) { + if (!isVisited(e)) { + // found an unexplored edge, explore it + visit(e); + Vertex w = graph.opposite(v, e); + if (!isVisited(w)) { + // w is unexplored, this is a discovery edge + traverseDiscovery(e, v); + if (isDone()) break; + visitResult = dfsTraversal(w); // get result from DFS-tree child + if (isDone()) break; + } + else { + // w is explored, this is a back edge + traverseBack(e, v); + if (isDone()) break; + } + } + } + } + if(!isDone()) + finishVisit(v); + return result(); + } + //end#fragment DFS2 + + //begin#fragment decorations + /** Mark a position (vertex or edge) as visited. */ + protected void visit(DecorablePosition p) throws InvalidKeyException{ + p.put(STATUS, VISITED); + } + /** Mark a position (vertex or edge) as unvisited. */ + protected void unVisit(DecorablePosition p) throws InvalidKeyException { + p.put(STATUS, UNVISITED); + } + /** Test if a position (vertex or edge) has been visited. */ + protected boolean isVisited(DecorablePosition p) throws InvalidKeyException { + return (p.get(STATUS) == VISITED); + } +//end#fragment decorations + + // Auxiliary methods (all initially null) for specializing a generic DFS +//begin#fragment auxiliary + /** Setup method that is called prior to the DFS execution. */ + protected void setup() {} + /** Initializes result (called first, once per vertex visited). */ + protected void initResult() {} + /** Called when we encounter a vertex (v). */ + protected void startVisit(Vertex v) {} + /** Called after we finish the visit for a vertex (v). */ + protected void finishVisit(Vertex v) {} + /** Called when we traverse a discovery edge (e) from a vertex (from). */ + protected void traverseDiscovery(Edge e, Vertex from) {} + /** Called when we traverse a back edge (e) from a vertex (from). */ + protected void traverseBack(Edge e, Vertex from) {} + /** Determines whether the traversal is done early. */ + protected boolean isDone() { return false; /* default value */ } + /** Returns a result of a visit (if needed). */ + protected R result() { return null; /* default value */ } + /** Returns the final result of the DFS execute method. */ + protected R finalResult(R r) { return r; /* default value */ } +//end#fragment auxiliary +//begin#fragment Tail +} // end of DFS class +//end#fragment Tail diff --git a/graph/Dijkstra.java b/graph/Dijkstra.java new file mode 100644 index 0000000..15688a1 --- /dev/null +++ b/graph/Dijkstra.java @@ -0,0 +1,102 @@ +package graph; + +import priorityqueue.AdaptablePriorityQueue; +import priorityqueue.Entry; +import priorityqueue.heap.HeapAdaptablePriorityQueue; +import utility.DefaultComparator; + +import java.security.InvalidKeyException; + +/** + * Dijkstra's algorithm for the single-source shortest path problem in + * an undirected graph whose edges have integer weights. + * + *

To execute the algorithm, use the {@link + * #execute(Graph,Vertex,Object) execute} method, and then make + * subsequent calls to the {@link #getDist(Vertex) getDist} method to + * obtain the shortest distance from the start to any given vertex. + * + * @author Roberto Tamassia, Michael Goodrich, Eric Zamore + */ + +//begin#fragment execute +/* Dijkstra's algorithm for the single-source shortest path problem + * in an undirected graph whose edges have non-negative integer weights. */ +public class Dijkstra { + /** Infinity value. */ + protected static final Integer INFINITE = Integer.MAX_VALUE; + /** Input graph. */ + protected Graph graph; + /** Decoration key for edge weights */ + protected Object WEIGHT; + /** Decoration key for vertex distances */ + protected Object DIST = new Object(); + /** Decoration key for entries in the priority queue */ + protected Object ENTRY = new Object(); + /** Auxiliary priority queue. */ + protected AdaptablePriorityQueue> Q; + /** Executes Dijkstra's algorithm. + * @param g Input graph + * @param s Source vertex + * @param w Weight decoration object */ + public void execute(Graph g, Vertex s, Object w) throws InvalidKeyException{ + graph = g; + WEIGHT = w; + DefaultComparator dc = new DefaultComparator(); + Q = new HeapAdaptablePriorityQueue>(dc); + dijkstraVisit(s); + } + /** Get the distance of a vertex from the source vertex. +//end#fragment execute + * This method returns the length of a shortest path from the source + * to u after {@link #execute(Graph,Vertex,Object) execute} + * has been called. +//begin#fragment execute + * @param u Start vertex for the shortest path tree */ + public int getDist(Vertex u) throws InvalidKeyException{ + return (Integer) u.get(DIST); + } +//end#fragment execute + + //begin#fragment dijkstraVisit + /** The actual execution of Dijkstra's algorithm. + * @param v source vertex. + */ + protected void dijkstraVisit (Vertex v) throws InvalidKeyException{ + // store all the vertices in priority queue Q + for (Vertex u: graph.vertices()) { + int u_dist; + if (u==v) + u_dist = 0; + else + u_dist = INFINITE; + Entry> u_entry = Q.insert(u_dist, u); // autoboxing + u.put(ENTRY, u_entry); + } + // grow the cloud, one vertex at a time + while (!Q.isEmpty()) { + // remove from Q and insert into cloud a vertex with minimum distance + Entry> u_entry = Q.min(); + Vertex u = u_entry.getValue(); + int u_dist = u_entry.getKey(); + Q.remove(u_entry); // remove u from the priority queue + u.put(DIST,u_dist); // the distance of u is final + u.remove(ENTRY); // remove the entry decoration of u + if (u_dist == INFINITE) + continue; // unreachable vertices are not processed + // examine all the neighbors of u and update their distances + for (Edge e: graph.incidentEdges(u)) { + Vertex z = graph.opposite(u,e); + Entry> z_entry + = (Entry>) z.get(ENTRY); + if (z_entry != null) { // check that z is in Q, i.e., not in the cloud + int e_weight = (Integer) e.get(WEIGHT); + int z_dist = z_entry.getKey(); + if ( u_dist + e_weight < z_dist ) // relaxation of edge e = (u,z) + Q.replaceKey(z_entry, u_dist + e_weight); + } + } + } + } + //end#fragment dijkstraVisit +} // end of Dijkstra class diff --git a/graph/FindCycleDFS.java b/graph/FindCycleDFS.java new file mode 100644 index 0000000..c7cbd25 --- /dev/null +++ b/graph/FindCycleDFS.java @@ -0,0 +1,58 @@ +package graph; +//begin#fragment FindCycleDFS + +import position.NodePositionList; +import position.Position; +import position.PositionList; + +/** This class specializes DFS to find a cycle. */ +//end#fragment FindCycleDFS + /* @author Roberto Tamassia, Michael Goodrich, Eric Zamore + */ +//begin#fragment FindCycleDFS +public class FindCycleDFS + extends DFS> { + protected PositionList cycle; // sequence of edges of the cycle + protected boolean done; + protected Vertex cycleStart; +//end#fragment FindCycleDFS + + /** + * Executes the DFS algorithm. + * @return collection containing the vertices and + * edges of a cycle. + */ +//begin#fragment FindCycleDFS + public void setup() { + cycle = new NodePositionList(); + done = false; + } + protected void startVisit(Vertex v) { cycle.addLast(v); } + protected void finishVisit(Vertex v) { + cycle.remove(cycle.last()); // remove v from cycle + if (!cycle.isEmpty()) cycle.remove(cycle.last()); // remove edge into v from cycle + } + protected void traverseDiscovery(Edge e, Vertex from) { + cycle.addLast(e); + } + protected void traverseBack(Edge e, Vertex from) { + cycle.addLast(e); // back edge e creates a cycle + cycleStart = graph.opposite(from, e); + cycle.addLast(cycleStart); // first vertex completes the cycle + done = true; + } + protected boolean isDone() { return done; } + public Iterable finalResult(Iterable r) { + // remove the vertices and edges from start to cycleStart + if (!cycle.isEmpty()) { + for (Position p: cycle.positions()) { + if (p.element() == cycleStart) + break; + cycle.remove(p); // remove vertex from cycle + } + } + return cycle; // list of the vertices and edges of the cycle + } +} +//end#fragment FindCycleDFS + diff --git a/graph/FindPathDFS.java b/graph/FindPathDFS.java new file mode 100644 index 0000000..deeed5d --- /dev/null +++ b/graph/FindPathDFS.java @@ -0,0 +1,43 @@ +package graph; + +//begin#fragment FindPathDFS + +import position.NodePositionList; +import position.Position; +import position.PositionList; + +/** Class specializing DFS to find a path between a start vertex and a target + * vertex. It assumes the target vertex is passed as the info object to the + * execute method. It returns an iterable list of the vertices and edges + * comprising the path from start to info. The returned path is empty if + * info is unreachable from start. */ +public class FindPathDFS + extends DFS, Iterable> { + protected PositionList path; + protected boolean done; + /** Setup method to initialize the path. */ + public void setup() { + path = new NodePositionList(); + done = false; + } + protected void startVisit(Vertex v) { + path.addLast(v); // add vertex v to path + if (v == info) + done = true; + } + protected void finishVisit(Vertex v) { + path.remove(path.last()); // remove v from path + if(!path.isEmpty()) // if v is not the start vertex + path.remove(path.last()); // remove discovery edge into v from path + } + protected void traverseDiscovery(Edge e, Vertex from) { + path.addLast(e); // add edge e to the path + } + protected boolean isDone() { + return done; + } + public Iterable finalResult(Iterable r) { + return path; + } +} +//end#fragment FindPathDFS diff --git a/graph/Kruskal.java b/graph/Kruskal.java new file mode 100644 index 0000000..d7594bf --- /dev/null +++ b/graph/Kruskal.java @@ -0,0 +1,52 @@ +package graph; + + +import partition.ListPartition; +import partition.Partition; +import position.NodePositionList; +import position.PositionList; +import priorityqueue.Entry; +import priorityqueue.PriorityQueue; +import priorityqueue.heap.HeapPriorityQueue; + +import java.security.InvalidKeyException; + +public class Kruskal { + protected Graph graph; + protected Object WEIGHT; + protected PositionList> EList; + + protected PriorityQueue> Q; + + public Iterable> execute(Graph g, Object w) throws InvalidKeyException{ + graph = g; + WEIGHT = w; + Q = new HeapPriorityQueue>(); + EList = new NodePositionList>(); + KruskalAlg(); + return EList; + } + + protected void KruskalAlg() throws InvalidKeyException{ + Partition> P = new ListPartition>(); + + for (Vertex w : graph.vertices()) + P.makeSet(w); + + for (Edge e : graph.edges()) + Q.insert((Double) e.get(WEIGHT), e); + + while (EList.size() < graph.numVertices() - 1) { + Entry> e_entry = Q.removeMin(); + Edge e = e_entry.getValue(); + Vertex endV[] = graph.endVertices(e); + Vertex u = endV[0]; + Vertex v = endV[1]; + + if (P.find(u) != P.find(v)) { + P.union(P.find(u), P.find(v)); + EList.addLast(e); + } + } + } +} diff --git a/graph/gioel.rar b/graph/gioel.rar new file mode 100644 index 0000000..39111f1 Binary files /dev/null and b/graph/gioel.rar differ