continuata implementazione di graph. bfs dfs kruskal dijkstra

This commit is contained in:
2014-05-28 00:52:03 +02:00
parent 395cf8a6e1
commit d6f43a646f
9 changed files with 566 additions and 0 deletions

131
graph/BFS.java Normal file
View File

@@ -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<V, E, I, R> {
protected Graph<V, E> graph;
protected Vertex<V> 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<PositionList<Vertex<V>>> layers;
public R execute(Graph<V, E> g, Vertex<V> s, I in) throws InvalidKeyException{
graph = g;
layers = new ArrayIndexList<PositionList<Vertex<V>>>(
graph.numVertices());
start = s;
info = in;
for (Vertex<V> v : graph.vertices())
unVisit(v);
for (Edge<E> e : graph.edges())
unVisit(e);
setup();
return finalResult(bfsTraversal(start));
}
protected void setup() {
}
protected R bfsTraversal(Vertex<V> v) throws InvalidKeyException{
initResult();
if (!isDone())
startVisit(v);
if (!isDone()) {
visit(v);
layers.add(0, new NodePositionList<Vertex<V>>());
layers.get(0).addLast(v);
}
int i = 0;
while (!layers.get(i).isEmpty()) {
layers.add(i + 1, new NodePositionList<Vertex<V>>());
for (Vertex<V> vertexInLayer : layers.get(i)) {
for (Edge<E> e : graph.incidentEdges(vertexInLayer)) {
if (!isVisited(e)) {
visit(e);
Vertex<V> 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> v) {
}
protected void traverseCross(Edge<E> e, Vertex<V> v) {
}
protected void traverseDiscovery(Edge<E> e, Vertex<V> v) {
}
protected void finishVisit(Vertex<V> 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;
}
}

39
graph/ComponentsBFS.java Normal file
View File

@@ -0,0 +1,39 @@
//gioel
package graph;
import java.security.InvalidKeyException;
public class ComponentsBFS<V, E> extends BFS<V, E, Object, Integer> {
protected Integer compNumber;
protected Object COMPONENT = new Object();
protected void setup() {
compNumber = 1;
}
protected void startVisit(Vertex<V> v) {
try {
v.put(COMPONENT, compNumber);
}
catch (InvalidKeyException e){
}
}
protected Integer finalResult(Integer bfsResult) {
try {
for(Vertex<V> v : graph.vertices())
if(!isVisited(v)) {
compNumber++;
bfsTraversal(v);
}
return compNumber;
}
catch (InvalidKeyException e){
}
return null;
}
}

35
graph/ComponentsDFS.java Normal file
View File

@@ -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<V, E> extends DFS<V, E, Object, Integer> {
protected Integer compNumber; // Connected component number
protected Object COMPONENT = new Object(); // Connected comp. selector
protected void setup() { compNumber = 1; }
protected void startVisit(Vertex<V> v) {
try{
v.put(COMPONENT, compNumber);
}
catch (InvalidKeyException e){
//
}
}
protected Integer finalResult(Integer dfsResult) {
try{
for (Vertex<V> 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

106
graph/DFS.java Normal file
View File

@@ -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<V, E, I, R> {
protected Graph<V, E> graph; // The graph being traversed
protected Vertex<V> 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<V, E> g, Vertex<V> s, I in) throws InvalidKeyException {
graph = g;
start = s;
info = in;
for(Vertex<V> v: graph.vertices()) unVisit(v); // mark vertices as unvisited
for(Edge<E> 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> v) throws InvalidKeyException{
initResult();
if (!isDone())
startVisit(v);
if (!isDone()) {
visit(v);
for (Edge<E> e: graph.incidentEdges(v)) {
if (!isVisited(e)) {
// found an unexplored edge, explore it
visit(e);
Vertex<V> 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> v) {}
/** Called after we finish the visit for a vertex (v). */
protected void finishVisit(Vertex<V> v) {}
/** Called when we traverse a discovery edge (e) from a vertex (from). */
protected void traverseDiscovery(Edge<E> e, Vertex<V> from) {}
/** Called when we traverse a back edge (e) from a vertex (from). */
protected void traverseBack(Edge<E> e, Vertex<V> 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

102
graph/Dijkstra.java Normal file
View File

@@ -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.
*
* <p>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<V, E> {
/** Infinity value. */
protected static final Integer INFINITE = Integer.MAX_VALUE;
/** Input graph. */
protected Graph<V, E> 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<Integer, Vertex<V>> Q;
/** Executes Dijkstra's algorithm.
* @param g Input graph
* @param s Source vertex
* @param w Weight decoration object */
public void execute(Graph<V, E> g, Vertex<V> s, Object w) throws InvalidKeyException{
graph = g;
WEIGHT = w;
DefaultComparator dc = new DefaultComparator();
Q = new HeapAdaptablePriorityQueue<Integer, Vertex<V>>(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 <tt>u</tt> 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<V> 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> v) throws InvalidKeyException{
// store all the vertices in priority queue Q
for (Vertex<V> u: graph.vertices()) {
int u_dist;
if (u==v)
u_dist = 0;
else
u_dist = INFINITE;
Entry<Integer, Vertex<V>> 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<Integer, Vertex<V>> u_entry = Q.min();
Vertex<V> 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> e: graph.incidentEdges(u)) {
Vertex<V> z = graph.opposite(u,e);
Entry<Integer, Vertex<V>> z_entry
= (Entry<Integer, Vertex<V>>) 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

58
graph/FindCycleDFS.java Normal file
View File

@@ -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<V, E>
extends DFS<V, E, Object, Iterable<Position>> {
protected PositionList<Position> cycle; // sequence of edges of the cycle
protected boolean done;
protected Vertex<V> 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<Position>();
done = false;
}
protected void startVisit(Vertex<V> v) { cycle.addLast(v); }
protected void finishVisit(Vertex<V> 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> e, Vertex<V> from) {
cycle.addLast(e);
}
protected void traverseBack(Edge<E> e, Vertex<V> 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<Position> finalResult(Iterable<Position> r) {
// remove the vertices and edges from start to cycleStart
if (!cycle.isEmpty()) {
for (Position<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

43
graph/FindPathDFS.java Normal file
View File

@@ -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<V, E>
extends DFS<V, E, Vertex<V>, Iterable<Position>> {
protected PositionList<Position> path;
protected boolean done;
/** Setup method to initialize the path. */
public void setup() {
path = new NodePositionList<Position>();
done = false;
}
protected void startVisit(Vertex<V> v) {
path.addLast(v); // add vertex v to path
if (v == info)
done = true;
}
protected void finishVisit(Vertex<V> 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> e, Vertex<V> from) {
path.addLast(e); // add edge e to the path
}
protected boolean isDone() {
return done;
}
public Iterable<Position> finalResult(Iterable<Position> r) {
return path;
}
}
//end#fragment FindPathDFS

52
graph/Kruskal.java Normal file
View File

@@ -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<V, E> {
protected Graph<V, E> graph;
protected Object WEIGHT;
protected PositionList<Edge<E>> EList;
protected PriorityQueue<Double, Edge<E>> Q;
public Iterable<Edge<E>> execute(Graph<V, E> g, Object w) throws InvalidKeyException{
graph = g;
WEIGHT = w;
Q = new HeapPriorityQueue<Double, Edge<E>>();
EList = new NodePositionList<Edge<E>>();
KruskalAlg();
return EList;
}
protected void KruskalAlg() throws InvalidKeyException{
Partition<Vertex<V>> P = new ListPartition<Vertex<V>>();
for (Vertex<V> w : graph.vertices())
P.makeSet(w);
for (Edge<E> e : graph.edges())
Q.insert((Double) e.get(WEIGHT), e);
while (EList.size() < graph.numVertices() - 1) {
Entry<Double, Edge<E>> e_entry = Q.removeMin();
Edge<E> e = e_entry.getValue();
Vertex<V> endV[] = graph.endVertices(e);
Vertex<V> u = endV[0];
Vertex<V> v = endV[1];
if (P.find(u) != P.find(v)) {
P.union(P.find(u), P.find(v));
EList.addLast(e);
}
}
}
}

BIN
graph/gioel.rar Normal file

Binary file not shown.