package rpi.goldsd.graph;
import java.util.Enumeration;
import rpi.goldsd.container.*;
/**
* The Edge class is used to represent a single undirected
* edge between two vertices. An edge is associated with either
* zero or one GraphBase objects.
*
* @see GraphBase
* @see DirectedEdge
* @version 2.0, 4/19/98
* @author David Goldschmidt
*/
public class Edge implements Hashable
{
protected static final IntSequence I = new IntSequence();
protected static final Enumeration keys = I.sequence();
/* ****************** CONSTRUCTOR METHODS ****************** */
/**
* Constructs an undirected edge with the given pair of endpoint
* vertices, the initial Hashable object to be associated with
* this undirected edge, and the initial weight.
* @param startVertex the first endpoint vertex of this undirected edge.
* @param endVertex the second endpoint vertex of this undirected edge.
* @param data the Hashable object to be associated with this
* undirected edge.
* @param isWeighted indicates whether this edge is a directed edge.
* @param weight the initial weight of this undirected edge.
*/
protected Edge( Vertex startVertex, Vertex endVertex, Hashable data,
boolean isWeighted, double weight )
{
this.associatedGraph = null;
this.startVertex = startVertex;
this.endVertex = endVertex;
this.data = data;
this.isWeighted = isWeighted;
if ( isWeighted ) this.weight = weight;
}
/**
* Constructs an undirected edge with the given pair of endpoint
* vertices, the initial Hashable object to be associated with
* this undirected edge, and the initial weight.
* @param startVertex the first endpoint vertex of this undirected edge.
* @param endVertex the second endpoint vertex of this undirected edge.
* @param data the Hashable object to be associated with this
* undirected edge.
* @param weight the initial weight of this undirected edge.
*/
public Edge( Vertex startVertex, Vertex endVertex, Hashable data,
double weight )
{
this( startVertex, endVertex, data, true, weight );
}
/**
* Constructs an undirected edge with the given pair of endpoint
* vertices, and the initial weight.
* @param startVertex the first endpoint vertex of this undirected edge.
* @param endVertex the second endpoint vertex of this undirected edge.
* @param weight the initial weight of this undirected edge.
*/
public Edge( Vertex startVertex, Vertex endVertex, double weight )
{
this( startVertex, endVertex, (Hashable)keys.nextElement(), true, weight );
}
/**
* Constructs an undirected edge with the given pair of endpoint
* vertices, the initial Hashable object to be associated with
* this undirected edge.
* @param startVertex the first endpoint vertex of this undirected edge.
* @param endVertex the second endpoint vertex of this undirected edge.
* @param data the Hashable object to be associated with this
* undirected edge.
*/
public Edge( Vertex startVertex, Vertex endVertex, Hashable data )
{
this( startVertex, endVertex, data, false, 0.0 );
}
/**
* Constructs an undirected edge with the given pair of endpoint
* vertices.
* @param startVertex the first endpoint vertex of this undirected edge.
* @param endVertex the second endpoint vertex of this undirected edge.
*/
public Edge( Vertex startVertex, Vertex endVertex )
{
this( startVertex, endVertex, (Hashable)keys.nextElement(), false, 0.0 );
}
/**
* The default constructor is not to be used, since an undirected edge
* must have a given start and end vertex.
*/
protected Edge() { }
/* ****************** ACCESSOR METHODS ****************** */
/**
* Returns a reference to the Hashable object that is
* associated with this undirected edge.
* @return a reference to the Hashable object that is
* associated with this undirected edge.
*/
public Hashable data() { return data; }
/**
* Returns the second vertex endpoint of this undirected edge.
* Note that the name endVertex does not imply a directed edge.
* @return the second vertex endpoint of this undirected edge.
*/
public Vertex endVertex() { return endVertex; }
/**
* Returns a reference to the graph that contains this undirected
* edge, if any.
* @return a reference to the graph that contains this undirected
* edge; or null if this undirected edge is not
* associated with a graph.
*/
public GraphBase graph() { return associatedGraph; }
/**
* Returns the hash value of the Hashable data associated with
* this edge.
* @return the hash value of the Hashable data associated with
* this edge.
*/
public int hash() { return data.hash(); }
/**
* Returns the hash value of the Hashable data associated with
* this edge.
* @param tableSize the size of the table that will potentially hold this
* Edge object and others.
* @return the hash value of the Hashable data associated with
* this edge.
*/
public int hash( int tableSize ) { return data.hash( tableSize ); }
/**
* Tests if two edges are "equal" based on their Hashable data
* objects.
* @param C the right-hand side of the comparison.
* @return true if this edge is "equal" to the given edge
* C based on the Hashable data objects;
* false otherwise.
*/
public boolean isEqualTo( Comparable C )
{
if ( C instanceof Edge ) return data.isEqualTo( ((Edge)C).data() );
else return data.isEqualTo( C );
}
/**
* Tests if this undirected edge is associated with a graph.
* @return true if this undirected edge is associated
* with a graph; false otherwise.
*/
public boolean isInGraph() { return ( associatedGraph != null ); }
/**
* Tests if this undirected edge is associated with the given graph.
* @param G the graph to test.
* @return true if this undirected edge is associated with
* the given graph G; false otherwise.
*/
public boolean isInGraph( GraphBase G )
{
return ( associatedGraph == G );
}
/**
* Tests if one edge is "less than" another based on their Hashable
* data objects.
* @param C the right-hand side of the comparison.
* @return true if this edge is "less than" the given edge
* C based on the Hashable data objects;
* false otherwise.
*/
public boolean isLessThan( Comparable C )
{
if ( C instanceof Edge ) return data.isLessThan( ((Edge)C).data() );
else return data.isLessThan( C );
}
/**
* Tests if this undirected edge is a self-loop.
* @return true if this undirected edge is a self-loop (i.e. both
* endpoint vertices are the same); false otherwise.
*/
public boolean isSelfLoop() { return ( startVertex == endVertex ); }
/**
* Tests if this undirected edge is a weighted edge.
* @return true if this undirected edge is a weighted
* edge; false otherwise.
*/
public boolean isWeighted() { return isWeighted; }
/**
* Returns the first vertex endpoint of this undirected edge.
* Note that the name startVertex does not imply a directed edge.
* @return the first vertex endpoint of this undirected edge.
*/
public Vertex startVertex() { return startVertex; }
/**
* Returns a String representation of this undirected edge.
* The toString() method is applied to the Hashable
* object that is associated with this edge.
* @return a String representation of this undirected edge.
*/
public String toString()
{
String s = "" + data;
if ( isWeighted )
s += "[W" + weight + "]";
return s;
}
/**
* Traverses this undirected edge from a given vertex, returning
* the destination vertex.
* @param V the vertex from which the traversal begins.
* @return the vertex this undirected edge is adjacent to from V;
* or null if V is not one of the endpoint
* vertices of this undirected edge.
*/
public Vertex traverseFrom( Vertex V )
{
if ( startVertex == V )
return endVertex;
else if ( endVertex == V )
return startVertex;
else
return null;
}
/**
* Returns the weight of this undirected edge, if any.
* @return the weight of this undirected edge; or null
* if there is no weight associated with this undirected edge.
*/
public double weight() { return weight; }
/* ****************** MUTATOR METHODS ****************** */
/**
* Sets the Hashable object that is associated with this edge.
* @param data the new Hashable object.
* @return the old Hashable object associated with this edge.
*/
public Hashable setData( Hashable data )
{
Hashable oldData = this.data;
if ( isInGraph() )
associatedGraph.rehash( oldData, data, this );
else
this.data = data;
return oldData;
}
/**
* Sets the associatedGraph reference to the given graph G.
* @param G the graph that this undirected edge is to be associated with.
*/
protected void setInGraph( GraphBase G ) { associatedGraph = G; }
/**
* Sets the weight of this edge.
* @param weight the weight to be associated with this edge.
* @return the old weight of this edge; or null if there
* was no weight associated with this edge.
*/
public double setWeight( double weight )
{
double oldWeight = this.weight;
this.weight = weight;
return oldWeight;
}
/* ****************** CLASS ATTRIBUTES ****************** */
/**
* A reference to the graph that this undirected edge is associated
* with; or null if this undirected edge is not associated
* with a graph.
*/
protected GraphBase associatedGraph;
/**
* A reference to the Hashable object associated with this
* undirected edge.
*/
protected Hashable data;
/**
* A reference to the second vertex endpoint associated with this
* undirected edge.
*/
protected Vertex endVertex;
/** A flag used to indicate whether this edge is weighted. */
protected boolean isWeighted;
/**
* A reference to the first vertex endpoint associated with this
* undirected edge.
*/
protected Vertex startVertex;
/** The weight associated with this undirected edge. */
protected double weight;
/** Used by the static Algorithms class. */
protected int status;
}