abstractbasegraph.java
来自「JAVA图论的算法包。用过觉得还不错」· Java 代码 · 共 1,223 行 · 第 1/3 页
JAVA
1,223 行
/* ==========================================
* 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.
*/
/* ----------------------
* AbstractBaseGraph.java
* ----------------------
* (C) Copyright 2003-2007, by Barak Naveh and Contributors.
*
* Original Author: Barak Naveh
* Contributor(s): John V. Sichi
* Christian Hammer
*
* $Id: AbstractBaseGraph.java 619 2008-08-07 07:52:36Z perfecthash $
*
* Changes
* -------
* 24-Jul-2003 : Initial revision (BN);
* 10-Aug-2003 : General edge refactoring (BN);
* 06-Nov-2003 : Change edge sharing semantics (JVS);
* 07-Feb-2004 : Enabled serialization (BN);
* 11-Mar-2004 : Made generic (CH);
* 01-Jun-2005 : Added EdgeListFactory (JVS);
* 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.util.*;
/**
* The most general implementation of the {@link org.jgrapht.Graph} interface.
* Its subclasses add various restrictions to get more specific graphs. The
* decision whether it is directed or undirected is decided at construction time
* and cannot be later modified (see constructor for details).
*
* <p>This graph implementation guarantees deterministic vertex and edge set
* ordering (via {@link LinkedHashMap} and {@link LinkedHashSet}).</p>
*
* @author Barak Naveh
* @since Jul 24, 2003
*/
public abstract class AbstractBaseGraph<V, E>
extends AbstractGraph<V, E>
implements Graph<V, E>,
Cloneable,
Serializable
{
//~ Static fields/initializers ---------------------------------------------
private static final long serialVersionUID = -1263088497616142427L;
private static final String LOOPS_NOT_ALLOWED = "loops not allowed";
//~ Instance fields --------------------------------------------------------
boolean allowingLoops;
private EdgeFactory<V, E> edgeFactory;
private EdgeSetFactory<V, E> edgeSetFactory;
private Map<E, IntrusiveEdge> edgeMap;
private transient Set<E> unmodifiableEdgeSet = null;
private transient Set<V> unmodifiableVertexSet = null;
private Specifics specifics;
private boolean allowingMultipleEdges;
private transient TypeUtil<V> vertexTypeDecl = null;
//~ Constructors -----------------------------------------------------------
/**
* Construct a new pseudograph. The pseudograph can either be directed or
* undirected, depending on the specified edge factory.
*
* @param ef the edge factory of the new graph.
* @param allowMultipleEdges whether to allow multiple edges or not.
* @param allowLoops whether to allow edges that are self-loops or not.
*
* @throws NullPointerException if the specified edge factory is <code>
* null</code>.
*/
public AbstractBaseGraph(
EdgeFactory<V, E> ef,
boolean allowMultipleEdges,
boolean allowLoops)
{
if (ef == null) {
throw new NullPointerException();
}
edgeMap = new LinkedHashMap<E, IntrusiveEdge>();
edgeFactory = ef;
allowingLoops = allowLoops;
allowingMultipleEdges = allowMultipleEdges;
specifics = createSpecifics();
this.edgeSetFactory = new ArrayListFactory<V, E>();
}
//~ Methods ----------------------------------------------------------------
/**
* @see Graph#getAllEdges(Object, Object)
*/
public Set<E> getAllEdges(V sourceVertex, V targetVertex)
{
return specifics.getAllEdges(sourceVertex, targetVertex);
}
/**
* Returns <code>true</code> if and only if self-loops are allowed in this
* graph. A self loop is an edge that its source and target vertices are the
* same.
*
* @return <code>true</code> if and only if graph loops are allowed.
*/
public boolean isAllowingLoops()
{
return allowingLoops;
}
/**
* Returns <code>true</code> if and only if multiple edges are allowed in
* this graph. The meaning of multiple edges is that there can be many edges
* going from vertex v1 to vertex v2.
*
* @return <code>true</code> if and only if multiple edges are allowed.
*/
public boolean isAllowingMultipleEdges()
{
return allowingMultipleEdges;
}
/**
* @see Graph#getEdge(Object, Object)
*/
public E getEdge(V sourceVertex, V targetVertex)
{
return specifics.getEdge(sourceVertex, targetVertex);
}
/**
* @see Graph#getEdgeFactory()
*/
public EdgeFactory<V, E> getEdgeFactory()
{
return edgeFactory;
}
/**
* Set the {@link EdgeSetFactory} to use for this graph. Initially, a graph
* is created with a default implementation which always supplies an {@link
* java.util.ArrayList} with capacity 1.
*
* @param edgeSetFactory factory to use for subsequently created edge sets
* (this call has no effect on existing edge sets)
*/
public void setEdgeSetFactory(EdgeSetFactory<V, E> edgeSetFactory)
{
this.edgeSetFactory = edgeSetFactory;
}
/**
* @see Graph#addEdge(Object, Object)
*/
public E addEdge(V sourceVertex, V targetVertex)
{
assertVertexExist(sourceVertex);
assertVertexExist(targetVertex);
if (!allowingMultipleEdges
&& containsEdge(sourceVertex, targetVertex))
{
return null;
}
if (!allowingLoops && sourceVertex.equals(targetVertex)) {
throw new IllegalArgumentException(LOOPS_NOT_ALLOWED);
}
E e = edgeFactory.createEdge(sourceVertex, targetVertex);
if (containsEdge(e)) { // this restriction should stay!
return null;
} else {
IntrusiveEdge intrusiveEdge =
createIntrusiveEdge(e, sourceVertex, targetVertex);
edgeMap.put(e, intrusiveEdge);
specifics.addEdgeToTouchingVertices(e);
return e;
}
}
/**
* @see Graph#addEdge(Object, Object, Object)
*/
public boolean addEdge(V sourceVertex, V targetVertex, E e)
{
if (e == null) {
throw new NullPointerException();
} else if (containsEdge(e)) {
return false;
}
assertVertexExist(sourceVertex);
assertVertexExist(targetVertex);
if (!allowingMultipleEdges
&& containsEdge(sourceVertex, targetVertex))
{
return false;
}
if (!allowingLoops && sourceVertex.equals(targetVertex)) {
throw new IllegalArgumentException(LOOPS_NOT_ALLOWED);
}
IntrusiveEdge intrusiveEdge =
createIntrusiveEdge(e, sourceVertex, targetVertex);
edgeMap.put(e, intrusiveEdge);
specifics.addEdgeToTouchingVertices(e);
return true;
}
private IntrusiveEdge createIntrusiveEdge(
E e,
V sourceVertex,
V targetVertex)
{
IntrusiveEdge intrusiveEdge;
if (e instanceof IntrusiveEdge) {
intrusiveEdge = (IntrusiveEdge) e;
} else {
intrusiveEdge = new IntrusiveEdge();
}
intrusiveEdge.source = sourceVertex;
intrusiveEdge.target = targetVertex;
return intrusiveEdge;
}
/**
* @see Graph#addVertex(Object)
*/
public boolean addVertex(V v)
{
if (v == null) {
throw new NullPointerException();
} else if (containsVertex(v)) {
return false;
} else {
specifics.addVertex(v);
return true;
}
}
/**
* @see Graph#getEdgeSource(Object)
*/
public V getEdgeSource(E e)
{
return TypeUtil.uncheckedCast(
getIntrusiveEdge(e).source,
vertexTypeDecl);
}
/**
* @see Graph#getEdgeTarget(Object)
*/
public V getEdgeTarget(E e)
{
return TypeUtil.uncheckedCast(
getIntrusiveEdge(e).target,
vertexTypeDecl);
}
private IntrusiveEdge getIntrusiveEdge(E e)
{
if (e instanceof IntrusiveEdge) {
return (IntrusiveEdge) e;
}
return edgeMap.get(e);
}
/**
* Returns a shallow copy of this graph instance. Neither edges nor vertices
* are cloned.
*
* @return a shallow copy of this set.
*
* @throws RuntimeException
*
* @see java.lang.Object#clone()
*/
public Object clone()
{
try {
TypeUtil<AbstractBaseGraph<V, E>> typeDecl = null;
AbstractBaseGraph<V, E> newGraph =
TypeUtil.uncheckedCast(super.clone(), typeDecl);
newGraph.edgeMap = new LinkedHashMap<E, IntrusiveEdge>();
newGraph.edgeFactory = this.edgeFactory;
newGraph.unmodifiableEdgeSet = null;
newGraph.unmodifiableVertexSet = null;
// NOTE: it's important for this to happen in an object
// method so that the new inner class instance gets associated with
// the right outer class instance
newGraph.specifics = newGraph.createSpecifics();
Graphs.addGraph(newGraph, this);
return newGraph;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
/**
* @see Graph#containsEdge(Object)
*/
public boolean containsEdge(E e)
{
return edgeMap.containsKey(e);
}
/**
* @see Graph#containsVertex(Object)
*/
public boolean containsVertex(V v)
{
return specifics.getVertexSet().contains(v);
}
/**
* @see UndirectedGraph#degreeOf(Object)
*/
public int degreeOf(V vertex)
{
return specifics.degreeOf(vertex);
}
/**
* @see Graph#edgeSet()
*/
public Set<E> edgeSet()
{
if (unmodifiableEdgeSet == null) {
unmodifiableEdgeSet = Collections.unmodifiableSet(edgeMap.keySet());
}
return unmodifiableEdgeSet;
}
/**
* @see Graph#edgesOf(Object)
*/
public Set<E> edgesOf(V vertex)
{
return specifics.edgesOf(vertex);
}
/**
* @see DirectedGraph#inDegreeOf(Object)
*/
public int inDegreeOf(V vertex)
{
return specifics.inDegreeOf(vertex);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?