subgraph.java
来自「JAVA图论的算法包。用过觉得还不错」· Java 代码 · 共 543 行 · 第 1/2 页
JAVA
543 行
/* ==========================================
* JGraphT : a free Java graph-theory library
* ==========================================
*
* Project Info: http://jgrapht.sourceforge.net/
* Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh)
*
* (C) Copyright 2003-2007, by Barak Naveh and Contributors.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/* -------------
* Subgraph.java
* -------------
* (C) Copyright 2003-2007, by Barak Naveh and Contributors.
*
* Original Author: Barak Naveh
* Contributor(s): Christian Hammer
*
* $Id: Subgraph.java 641 2008-09-29 06:58:00Z perfecthash $
*
* Changes
* -------
* 24-Jul-2003 : Initial revision (BN);
* 26-Jul-2003 : Accurate constructors to avoid casting problems (BN);
* 10-Aug-2003 : Adaptation to new event model (BN);
* 23-Oct-2003 : Allowed non-listenable graph as base (BN);
* 07-Feb-2004 : Enabled serialization (BN);
* 11-Mar-2004 : Made generic (CH);
* 15-Mar-2004 : Integrity is now checked using Maps (CH);
* 20-Mar-2004 : Cancelled verification of element identity to base graph (BN);
* 21-Sep-2004 : Added induced subgraph (who?)
* 07-May-2006 : Changed from List<Edge> to Set<Edge> (JVS);
* 28-May-2006 : Moved connectivity info from edge to graph (JVS);
*
*/
package org.jgrapht.graph;
import java.io.*;
import java.util.*;
import org.jgrapht.*;
import org.jgrapht.event.*;
import org.jgrapht.util.*;
/**
* A subgraph is a graph that has a subset of vertices and a subset of edges
* with respect to some base graph. More formally, a subgraph G(V,E) that is
* based on a base graph Gb(Vb,Eb) satisfies the following <b><i>subgraph
* property</i></b>: V is a subset of Vb and E is a subset of Eb. Other than
* this property, a subgraph is a graph with any respect and fully complies with
* the <code>Graph</code> interface.
*
* <p>If the base graph is a {@link org.jgrapht.ListenableGraph}, the subgraph
* listens on the base graph and guarantees the subgraph property. If an edge or
* a vertex is removed from the base graph, it is automatically removed from the
* subgraph. Subgraph listeners are informed on such removal only if it results
* in a cascaded removal from the subgraph. If the subgraph has been created as
* an induced subgraph it also keeps track of edges being added to its vertices.
* If vertices are added to the base graph, the subgraph remains unaffected.</p>
*
* <p>If the base graph is <i>not</i> a ListenableGraph, then the subgraph
* property cannot be guaranteed. If edges or vertices are removed from the base
* graph, they are <i>not</i> removed from the subgraph.</p>
*
* <p>Modifications to Subgraph are allowed as long as the subgraph property is
* maintained. Addition of vertices or edges are allowed as long as they also
* exist in the base graph. Removal of vertices or edges is always allowed. The
* base graph is <i>never</i> affected by any modification made to the
* subgraph.</p>
*
* <p>A subgraph may provide a "live-window" on a base graph, so that changes
* made to its vertices or edges are immediately reflected in the base graph,
* and vice versa. For that to happen, vertices and edges added to the subgraph
* must be <i>identical</i> (that is, reference-equal and not only value-equal)
* to their respective ones in the base graph. Previous versions of this class
* enforced such identity, at a severe performance cost. Currently it is no
* longer enforced. If you want to achieve a "live-window"functionality, your
* safest tactics would be to NOT override the <code>equals()</code> methods of
* your vertices and edges. If you use a class that has already overridden the
* <code>equals()</code> method, such as <code>String</code>, than you can use a
* wrapper around it, or else use it directly but exercise a great care to avoid
* having different-but-equal instances in the subgraph and the base graph.</p>
*
* <p>This graph implementation guarantees deterministic vertex and edge set
* ordering (via {@link LinkedHashSet}).</p>
*
* @author Barak Naveh
* @see Graph
* @see Set
* @since Jul 18, 2003
*/
public class Subgraph<V, E, G extends Graph<V, E>>
extends AbstractGraph<V, E>
implements Serializable
{
//~ Static fields/initializers ---------------------------------------------
private static final long serialVersionUID = 3208313055169665387L;
private static final String NO_SUCH_EDGE_IN_BASE =
"no such edge in base graph";
private static final String NO_SUCH_VERTEX_IN_BASE =
"no such vertex in base graph";
//~ Instance fields --------------------------------------------------------
//
Set<E> edgeSet = new LinkedHashSet<E>(); // friendly to improve performance
Set<V> vertexSet = new LinkedHashSet<V>(); // friendly to improve
// performance
//
private transient Set<E> unmodifiableEdgeSet = null;
private transient Set<V> unmodifiableVertexSet = null;
private G base;
private boolean isInduced = false;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new Subgraph.
*
* @param base the base (backing) graph on which the subgraph will be based.
* @param vertexSubset vertices to include in the subgraph. If <code>
* null</code> then all vertices are included.
* @param edgeSubset edges to in include in the subgraph. If <code>
* null</code> then all the edges whose vertices found in the graph are
* included.
*/
public Subgraph(G base, Set<V> vertexSubset, Set<E> edgeSubset)
{
super();
this.base = base;
if (edgeSubset == null) {
isInduced = true;
}
if (base instanceof ListenableGraph) {
((ListenableGraph<V, E>) base).addGraphListener(
new BaseGraphListener());
}
addVerticesUsingFilter(base.vertexSet(), vertexSubset);
addEdgesUsingFilter(base.edgeSet(), edgeSubset);
}
/**
* Creates a new induced Subgraph. The subgraph will keep track of edges
* being added to its vertex subset as well as deletion of edges and
* vertices. If base it not listenable, this is identical to the call
* Subgraph(base, vertexSubset, null) .
*
* @param base the base (backing) graph on which the subgraph will be based.
* @param vertexSubset vertices to include in the subgraph. If <code>
* null</code> then all vertices are included.
*/
public Subgraph(G base, Set<V> vertexSubset)
{
this(base, vertexSubset, null);
}
//~ Methods ----------------------------------------------------------------
/**
* @see Graph#getAllEdges(Object, Object)
*/
public Set<E> getAllEdges(V sourceVertex, V targetVertex)
{
Set<E> edges = null;
if (containsVertex(sourceVertex) && containsVertex(targetVertex)) {
edges = new ArrayUnenforcedSet<E>();
Set<E> baseEdges = base.getAllEdges(sourceVertex, targetVertex);
for (Iterator<E> iter = baseEdges.iterator(); iter.hasNext();) {
E e = iter.next();
if (edgeSet.contains(e)) { // add if subgraph also contains
// it
edges.add(e);
}
}
}
return edges;
}
/**
* @see Graph#getEdge(Object, Object)
*/
public E getEdge(V sourceVertex, V targetVertex)
{
Set<E> edges = getAllEdges(sourceVertex, targetVertex);
if ((edges == null) || edges.isEmpty()) {
return null;
} else {
return edges.iterator().next();
}
}
/**
* @see Graph#getEdgeFactory()
*/
public EdgeFactory<V, E> getEdgeFactory()
{
return base.getEdgeFactory();
}
/**
* @see Graph#addEdge(Object, Object)
*/
public E addEdge(V sourceVertex, V targetVertex)
{
assertVertexExist(sourceVertex);
assertVertexExist(targetVertex);
if (!base.containsEdge(sourceVertex, targetVertex)) {
throw new IllegalArgumentException(NO_SUCH_EDGE_IN_BASE);
}
Set<E> edges = base.getAllEdges(sourceVertex, targetVertex);
for (Iterator<E> iter = edges.iterator(); iter.hasNext();) {
E e = iter.next();
if (!containsEdge(e)) {
edgeSet.add(e);
return e;
}
}
return null;
}
/**
* @see Graph#addEdge(Object, Object, Object)
*/
public boolean addEdge(V sourceVertex, V targetVertex, E e)
{
if (e == null) {
throw new NullPointerException();
}
if (!base.containsEdge(e)) {
throw new IllegalArgumentException(NO_SUCH_EDGE_IN_BASE);
}
assertVertexExist(sourceVertex);
assertVertexExist(targetVertex);
assert (base.getEdgeSource(e) == sourceVertex);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?