View Javadoc

1   /*
2    * Created on Apr 1, 2007
3    *
4    * Copyright (c) 2007, the JUNG Project and the Regents of the University 
5    * of California
6    * All rights reserved.
7    *
8    * This software is open-source under the BSD license; see either
9    * "license.txt" or
10   * http://jung.sourceforge.net/license.txt for a description.
11   */
12  package edu.uci.ics.jung.graph;
13  
14  import java.util.ArrayList;
15  import java.util.Collection;
16  import java.util.Collections;
17  import java.util.HashMap;
18  import java.util.Map;
19  
20  import org.apache.commons.collections15.Factory;
21  
22  import edu.uci.ics.jung.graph.util.EdgeType;
23  import edu.uci.ics.jung.graph.util.Pair;
24  
25  /**
26   * An implementation of <code>UndirectedGraph</code> that is suitable
27   * for sparse graphs.
28   */
29  @SuppressWarnings("serial")
30  public class UndirectedSparseGraph<V, E> extends AbstractTypedGraph<V, E>
31          implements UndirectedGraph<V, E>
32  {
33  
34      /**
35       * Returns a {@code Factory} that creates an instance of this graph type.
36       * @param <V> the vertex type for the graph factory
37       * @param <E> the edge type for the graph factory
38       */
39      public static <V,E> Factory<UndirectedGraph<V,E>> getFactory() {
40          return new Factory<UndirectedGraph<V,E>> () {
41  
42              public UndirectedGraph<V,E> create() {
43                  return new UndirectedSparseGraph<V,E>();
44              }
45          };
46      }
47  
48      protected Map<V, Map<V,E>> vertices; // Map of vertices to adjacency maps of vertices to incident edges
49      protected Map<E, Pair<V>> edges;    // Map of edges to incident vertex sets
50  
51      /**
52       * Creates an instance.
53       */
54      public UndirectedSparseGraph() {
55      	super(EdgeType.UNDIRECTED);
56          vertices = new HashMap<V, Map<V,E>>();
57          edges = new HashMap<E, Pair<V>>();
58      }
59  
60      @Override
61      public boolean addEdge(E edge, Pair<? extends V> endpoints, EdgeType edgeType)
62      {
63      	this.validateEdgeType(edgeType);
64          Pair<V> new_endpoints = getValidatedEndpoints(edge, endpoints);
65          if (new_endpoints == null)
66              return false;
67          
68          V v1 = new_endpoints.getFirst();
69          V v2 = new_endpoints.getSecond();
70          
71          if (findEdge(v1, v2) != null)
72              return false;
73          
74          edges.put(edge, new_endpoints);
75  
76          if (!vertices.containsKey(v1))
77              this.addVertex(v1);
78          
79          if (!vertices.containsKey(v2))
80              this.addVertex(v2);
81          
82          // map v1 to <v2, edge> and vice versa
83          vertices.get(v1).put(v2, edge);
84          vertices.get(v2).put(v1, edge);
85  
86          return true;
87      }
88  
89      public Collection<E> getInEdges(V vertex)
90      {
91          return this.getIncidentEdges(vertex);
92      }
93  
94      public Collection<E> getOutEdges(V vertex)
95      {
96          return this.getIncidentEdges(vertex);
97      }
98  
99      public Collection<V> getPredecessors(V vertex)
100     {
101         return this.getNeighbors(vertex);
102     }
103 
104     public Collection<V> getSuccessors(V vertex)
105     {
106         return this.getNeighbors(vertex);
107     }
108 
109     @Override
110     public E findEdge(V v1, V v2)
111     {
112         if (!containsVertex(v1) || !containsVertex(v2))
113             return null;
114         return vertices.get(v1).get(v2);
115     }
116     
117     @Override
118     public Collection<E> findEdgeSet(V v1, V v2)
119     {
120         if (!containsVertex(v1) || !containsVertex(v2))
121             return null;
122         ArrayList<E> edge_collection = new ArrayList<E>(1);
123 //        if (!containsVertex(v1) || !containsVertex(v2))
124 //            return edge_collection;
125         E e = findEdge(v1, v2);
126         if (e == null)
127             return edge_collection;
128         edge_collection.add(e);
129         return edge_collection;
130     }
131     
132     public Pair<V> getEndpoints(E edge)
133     {
134         return edges.get(edge);
135     }
136 
137     public V getSource(E directed_edge)
138     {
139         return null;
140     }
141 
142     public V getDest(E directed_edge)
143     {
144         return null;
145     }
146 
147     public boolean isSource(V vertex, E edge)
148     {
149         return false;
150     }
151 
152     public boolean isDest(V vertex, E edge)
153     {
154         return false;
155     }
156 
157     public Collection<E> getEdges()
158     {
159         return Collections.unmodifiableCollection(edges.keySet());
160     }
161 
162     public Collection<V> getVertices()
163     {
164         return Collections.unmodifiableCollection(vertices.keySet());
165     }
166 
167     public boolean containsVertex(V vertex)
168     {
169         return vertices.containsKey(vertex);
170     }
171 
172     public boolean containsEdge(E edge)
173     {
174         return edges.containsKey(edge);
175     }
176 
177     public int getEdgeCount()
178     {
179         return edges.size();
180     }
181 
182     public int getVertexCount()
183     {
184         return vertices.size();
185     }
186 
187     public Collection<V> getNeighbors(V vertex)
188     {
189         if (!containsVertex(vertex))
190             return null;
191         return Collections.unmodifiableCollection(vertices.get(vertex).keySet());
192     }
193 
194     public Collection<E> getIncidentEdges(V vertex)
195     {
196         if (!containsVertex(vertex))
197             return null;
198         return Collections.unmodifiableCollection(vertices.get(vertex).values());
199     }
200 
201     public boolean addVertex(V vertex)
202     {
203         if(vertex == null) {
204             throw new IllegalArgumentException("vertex may not be null");
205         }
206         if (!containsVertex(vertex)) {
207             vertices.put(vertex, new HashMap<V,E>());
208             return true;
209         } else {
210             return false;
211         }
212     }
213 
214     public boolean removeVertex(V vertex)
215     {
216         if (!containsVertex(vertex))
217             return false;
218 
219         // iterate over copy of incident edge collection
220         for (E edge : new ArrayList<E>(vertices.get(vertex).values()))
221             removeEdge(edge);
222         
223         vertices.remove(vertex);
224         return true;
225     }
226 
227     public boolean removeEdge(E edge)
228     {
229         if (!containsEdge(edge))
230             return false;
231         
232         Pair<V> endpoints = getEndpoints(edge);
233         V v1 = endpoints.getFirst();
234         V v2 = endpoints.getSecond();
235         
236         // remove incident vertices from each others' adjacency maps
237         vertices.get(v1).remove(v2);
238         vertices.get(v2).remove(v1);
239 
240         edges.remove(edge);
241         return true;
242     }
243 }