Commit 643d1f05 authored by sbalev's avatar sbalev

Modified and extended AbstractSpanningTree

parent a79a609d
......@@ -40,20 +40,25 @@ import org.graphstream.graph.Graph;
* <p>
* The result is stored in an edge attribute which name is defined by
* {@link #flagAttribute} and value is {@link #flagOn} if the edge is in the
* tree or {@link #flagOff} if not.
* tree or {@link #flagOff} if not. If {@link #flagAttribute} is {@code null}
* nothing is stored in the edges. If {@link #flagOn} is {@code null} edges in
* the tree are not tagged. If {@link #flagOff} is {@code null} edges out of the
* tree are not tagged.
* </p>
*
*
* <h2>Creating a spanning tree algorithm</h2>
*
* <p>
* Spanning tree algorithms have to extend this class and to implements the
* {@link #makeTree()} method. {@link #edgeOn(Edge)} and {@link #edgeOff(Edge)}
* methods have to be used to properly tag edge.
* {@link #makeTree()} and {@link #getTreeEdgesIterator()} methods.
* {@link #edgeOn(Edge)} and {@link #edgeOff(Edge)} methods have to be used to
* properly tag edges.
* </p>
*
* <p>
* A call to compute reset the values of edges attribute. Then a call to
* {@link #makeTree()} is done.
* {@link #makeTree()} is made.
* </p>
*
* <h2>Highlight the spanning tree in viewer</h2>
......@@ -130,14 +135,16 @@ public abstract class AbstractSpanningTree implements Algorithm {
protected Object flagOff;
/**
* Create a new SpanningTree algorithm.
* Create a new SpanningTree algorithm. By default edges are not tagged.
*/
public AbstractSpanningTree() {
this("SpanningTree.flag");
this(null, null, null);
}
/**
* Create a new SpanningTree algorithm.
* Create a new SpanningTree algorithm. Default flag attribute values are
* {@code true} for edges in the tree and {@code false} for the remaining
* edges.
*
* @param flagAttribute
* attribute used to compare edges
......@@ -160,8 +167,8 @@ public abstract class AbstractSpanningTree implements Algorithm {
*/
public AbstractSpanningTree(String flagAttribute, Object flagOn,
Object flagOff) {
graph = null;
this.flagAttribute = flagAttribute;
this.flagOn = flagOn;
this.flagOff = flagOff;
}
......@@ -173,17 +180,22 @@ public abstract class AbstractSpanningTree implements Algorithm {
* @return flag attribute
*/
public String getFlagAttribute() {
return this.flagAttribute;
return flagAttribute;
}
/**
* Set the flag attribute.
*
* @param newFlagAttribute
* new attribute used
* @param flagAttribute
* New attribute used. If {@code null} edges are not tagged.
* @throws IllegalStateException
* if {@link #init(Graph)} is already called
*/
public void setFlagAttribute(String newFlagAttribute) {
this.flagAttribute = newFlagAttribute;
public void setFlagAttribute(String flagAttribute) {
if (graph != null)
throw new IllegalStateException(
"Flag attribute can be set only before the algorithm is initialized");
this.flagAttribute = flagAttribute;
}
/**
......@@ -193,18 +205,22 @@ public abstract class AbstractSpanningTree implements Algorithm {
*/
public Object getFlagOn() {
return this.flagOn;
return flagOn;
}
/**
* Set value used to set that an edge is in the spanning tree.
*
* @param newFlagOn
* on value
* @param flagOn
* on value. If {@code null} edges in the tree are not tagged.
* @throws IllegalStateException
* if {@link #init(Graph)} is already called
*/
public void setFlagOn(Object newFlagOn) {
if (!this.flagOff.equals(newFlagOn))
this.flagOn = newFlagOn;
public void setFlagOn(Object flagOn) {
if (graph != null)
throw new IllegalStateException(
"Flag values can be set only before the algorithm is initialized");
this.flagOn = flagOn;
}
/**
......@@ -213,18 +229,22 @@ public abstract class AbstractSpanningTree implements Algorithm {
* @return off value
*/
public Object getFlagOff() {
return this.flagOff;
return flagOff;
}
/**
* Set value used to set that an edge is not in the spanning tree.
*
* @param newFlagOff
* off value
* off value. If {@code null} edges out of the tree are not tagged.
* @throws IllegalStateException
* if {@link #init(Graph)} is already called
*/
public void setFlagOff(Object newFlagOff) {
if (!this.flagOn.equals(newFlagOff))
this.flagOff = newFlagOff;
public void setFlagOff(Object flagOff) {
if (graph != null)
throw new IllegalStateException(
"Flag values can be set only before the algorithm is initialized");
this.flagOff = flagOff;
}
// Protected Access
......@@ -236,7 +256,12 @@ public abstract class AbstractSpanningTree implements Algorithm {
* edge to add
*/
protected void edgeOn(Edge e) {
e.changeAttribute(flagAttribute, flagOn);
if (flagAttribute != null) {
if (flagOn != null)
e.changeAttribute(flagAttribute, flagOn);
else
e.removeAttribute(flagAttribute);
}
}
/**
......@@ -246,27 +271,49 @@ public abstract class AbstractSpanningTree implements Algorithm {
* edge to remove
*/
protected void edgeOff(Edge e) {
e.changeAttribute(flagAttribute, flagOff);
if (flagAttribute != null) {
if (flagOff != null)
e.changeAttribute(flagAttribute, flagOff);
else
e.removeAttribute(flagAttribute);
}
}
/**
* Reset cluster and flag attribute values.
* Reset flag attribute values. All edges are tagged as being out of the tree.
*/
protected void resetFlags() {
Iterator<? extends Edge> iteE;
iteE = graph.getEdgeIterator();
while (iteE.hasNext())
edgeOff(iteE.next());
for (Edge edge : graph.getEachEdge())
edgeOff(edge);
}
// Abstract methods to be implemented by subclasses
/**
* Method that will be implemented by spanning tree's algorithms to build
* the tree.
*/
protected abstract void makeTree();
/**
* An iterator on the tree edges.
* @return An iterator on the tree edges
*/
public abstract <T extends Edge> Iterator<T> getTreeEdgesIterator();
/**
* Iterable view of the spanning tree edges. This implementation uses {@link #getTreeEdgesIterator()}.
* @return Iterable view of the tree edges.
*/
public <T extends Edge> Iterable<T> getTreeEdges() {
return new Iterable<T>() {
public Iterator<T> iterator() {
return getTreeEdgesIterator();
}
};
}
// Algorithm interface
/*
......
......@@ -358,4 +358,10 @@ public class Kruskal extends AbstractSpanningTree {
return o instanceof WeightEdgeComparator;
}
}
@Override
public <T extends Edge> Iterator<T> getTreeEdgesIterator() {
// TODO Auto-generated method stub
return null;
}
}
......@@ -350,4 +350,10 @@ public class Prim extends AbstractSpanningTree {
return o instanceof WeightEdgeComparator;
}
}
@Override
public <T extends Edge> Iterator<T> getTreeEdgesIterator() {
// TODO Auto-generated method stub
return null;
}
}
......@@ -114,11 +114,13 @@ public class DisjointSets<E> {
}
/**
* Adds a new set containing only {@code e} to the structure. If {@code e} already belongs
* to some of the disjoint sets, nothing happens.
* Adds a new set containing only {@code e} to the structure. If {@code e}
* already belongs to some of the disjoint sets, nothing happens.
*
* @param e The element to add as a singleton
* @return True if the new set is added and false if {@code e} already belongs to some set.
* @param e
* The element to add as a singleton
* @return True if the new set is added and false if {@code e} already
* belongs to some set.
*/
public boolean add(E e) {
Node x = map.get(e);
......@@ -130,10 +132,14 @@ public class DisjointSets<E> {
/**
* Checks if two elements belong to the same set.
* @param e1 An element
* @param e2 An element
* @return True if and only if belong to the same set.
* Note that if {@code e1} or {@code e2} do not belong to any set, false is returned.
*
* @param e1
* An element
* @param e2
* An element
* @return True if and only if belong to the same set. Note that if
* {@code e1} or {@code e2} do not belong to any set, false is
* returned.
*/
public boolean inSameSet(Object e1, Object e2) {
Node x1 = map.get(e1);
......@@ -146,10 +152,15 @@ public class DisjointSets<E> {
}
/**
* Union of the set containing {@code e1} and the set containing {@code e2}. After this operation {@code inSameSet(e1, e2)} will return true.
* If {@code e1} or {@code e2} do not belong to any set or if they already belong to the same set, nothing happens.
* @param e1 An element
* @param e2 An element
* Union of the set containing {@code e1} and the set containing {@code e2}.
* After this operation {@code inSameSet(e1, e2)} will return true. If
* {@code e1} or {@code e2} do not belong to any set or if they already
* belong to the same set, nothing happens.
*
* @param e1
* An element
* @param e2
* An element
*/
public void union(Object e1, Object e2) {
Node x1 = map.get(e1);
......@@ -163,15 +174,18 @@ public class DisjointSets<E> {
/**
* Checks if an element belongs to some of the disjoint sets.
* @param e An element
*
* @param e
* An element
* @return True if {@code e} belongs to some set.
*/
public boolean contains(Object e) {
return map.get(e) != null;
}
/**
* Reinitializes the structure. After this operation the structure contains no sets.
* Reinitializes the structure. After this operation the structure contains
* no sets.
*/
public void clear() {
for (Node node : map.values())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment