View Javadoc

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