55
66namespace Advanced . Algorithms . DataStructures . Graph . AdjacencyMatrix
77{
8-
98 /// <summary>
10- /// A directed graph implementation using dynamically growinng /shrinking adjacency matrix array.
9+ /// A directed graph implementation using dynamically growing /shrinking adjacency matrix array.
1110 /// IEnumerable enumerates all vertices.
1211 /// </summary>
13- public class Graph < T > : IEnumerable < T >
12+ public class Graph < T > : IGraph < T > , IEnumerable < T >
1413 {
15- public int VerticesCount => usedSize ;
14+ private BitArray [ ] matrix ;
1615
1716 private Dictionary < T , int > vertexIndices ;
1817 private Dictionary < int , T > reverseVertexIndices ;
18+ private Dictionary < T , GraphVertex < T > > vertexObjects ;
1919
20- private BitArray [ ] matrix ;
21-
22- private int maxSize ;
20+ private int maxSize => matrix . Length ;
2321 private int usedSize ;
2422 private int nextAvailableIndex ;
2523
24+ public int VerticesCount => usedSize ;
25+ public bool IsWeightedGraph => false ;
26+
2627 public Graph ( )
2728 {
28- maxSize = 1 ;
2929 vertexIndices = new Dictionary < T , int > ( ) ;
3030 reverseVertexIndices = new Dictionary < int , T > ( ) ;
31- matrix = new BitArray [ maxSize ] ;
31+ vertexObjects = new Dictionary < T , GraphVertex < T > > ( ) ;
32+
33+ matrix = new BitArray [ 1 ] ;
3234
3335 for ( int i = 0 ; i < maxSize ; i ++ )
3436 {
3537 matrix [ i ] = new BitArray ( maxSize ) ;
3638 }
3739 }
3840
41+ public IGraphVertex < T > ReferenceVertex => getReferenceVertex ( ) ;
42+ private GraphVertex < T > getReferenceVertex ( )
43+ {
44+ if ( this . VerticesCount == 0 )
45+ {
46+ throw new Exception ( "Empty graph." ) ;
47+ }
48+
49+ return vertexObjects [ this . First ( ) ] ;
50+ }
51+
3952 /// <summary>
4053 /// Add a new vertex to this graph.
4154 /// Time complexity: O(1).
@@ -64,6 +77,7 @@ public void AddVertex(T value)
6477
6578 vertexIndices . Add ( value , nextAvailableIndex ) ;
6679 reverseVertexIndices . Add ( nextAvailableIndex , value ) ;
80+ vertexObjects . Add ( value , new GraphVertex < T > ( this , value ) ) ;
6781
6882 nextAvailableIndex ++ ;
6983 usedSize ++ ;
@@ -103,6 +117,7 @@ public void RemoveVertex(T value)
103117
104118 reverseVertexIndices . Remove ( index ) ;
105119 vertexIndices . Remove ( value ) ;
120+ vertexObjects . Remove ( value ) ;
106121
107122 usedSize -- ;
108123
@@ -199,19 +214,37 @@ public IEnumerable<T> Edges(T vertex)
199214
200215 var index = vertexIndices [ vertex ] ;
201216
202- var result = new List < T > ( ) ;
217+ for ( int i = 0 ; i < maxSize ; i ++ )
218+ {
219+ if ( matrix [ i ] . Get ( index ) )
220+ {
221+ yield return reverseVertexIndices [ i ] ;
222+ }
223+ }
224+ }
225+
226+ public int EdgesCount ( T vertex )
227+ {
228+ if ( ! vertexIndices . ContainsKey ( vertex ) )
229+ {
230+ throw new ArgumentException ( "vertex is not in this graph." ) ;
231+ }
232+
233+ var count = 0 ;
234+ var index = vertexIndices [ vertex ] ;
203235
204236 for ( int i = 0 ; i < maxSize ; i ++ )
205237 {
206238 if ( matrix [ i ] . Get ( index ) )
207239 {
208- result . Add ( reverseVertexIndices [ i ] ) ;
240+ count ++ ;
209241 }
210242 }
211243
212- return result ;
244+ return count ;
213245 }
214246
247+
215248 private void doubleMatrixSize ( )
216249 {
217250 var newMatrix = new BitArray [ maxSize * 2 ] ;
@@ -237,7 +270,7 @@ private void doubleMatrixSize()
237270 {
238271 for ( int j = i ; j < maxSize ; j ++ )
239272 {
240- if ( matrix [ i ] . Get ( j ) && matrix [ j ] . Get ( i )
273+ if ( matrix [ i ] . Get ( j ) && matrix [ j ] . Get ( i )
241274 && reverseVertexIndices . ContainsKey ( i )
242275 && reverseVertexIndices . ContainsKey ( j ) )
243276 {
@@ -253,7 +286,6 @@ private void doubleMatrixSize()
253286 matrix = newMatrix ;
254287 vertexIndices = newVertexIndices ;
255288 reverseVertexIndices = newReverseIndices ;
256- maxSize *= 2 ;
257289 }
258290
259291 private void halfMatrixSize ( )
@@ -281,7 +313,7 @@ private void halfMatrixSize()
281313 {
282314 for ( int j = i ; j < maxSize ; j ++ )
283315 {
284- if ( matrix [ i ] . Get ( j ) && matrix [ j ] . Get ( i )
316+ if ( matrix [ i ] . Get ( j ) && matrix [ j ] . Get ( i )
285317 && reverseVertexIndices . ContainsKey ( i )
286318 && reverseVertexIndices . ContainsKey ( j ) )
287319 {
@@ -297,9 +329,10 @@ private void halfMatrixSize()
297329 matrix = newMatrix ;
298330 vertexIndices = newVertexIndices ;
299331 reverseVertexIndices = newReverseIndices ;
300- maxSize /= 2 ;
301332 }
302333
334+ public IEnumerable < IGraphVertex < T > > VerticesAsEnumberable => vertexObjects . Select ( x => x . Value ) ;
335+
303336 IEnumerator IEnumerable . GetEnumerator ( )
304337 {
305338 return GetEnumerator ( ) ;
@@ -309,5 +342,95 @@ public IEnumerator<T> GetEnumerator()
309342 {
310343 return vertexIndices . Select ( x => x . Key ) . GetEnumerator ( ) ;
311344 }
345+
346+ public bool ContainsVertex ( T key )
347+ {
348+ return vertexObjects . ContainsKey ( key ) ;
349+ }
350+
351+ public IGraphVertex < T > GetVertex ( T key )
352+ {
353+ return vertexObjects [ key ] ;
354+ }
355+
356+ IGraph < T > IGraph < T > . Clone ( )
357+ {
358+ return Clone ( ) ;
359+ }
360+
361+ public Graph < T > Clone ( )
362+ {
363+ var graph = new Graph < T > ( ) ;
364+
365+ foreach ( var vertex in this )
366+ {
367+ graph . AddVertex ( vertex ) ;
368+ }
369+
370+ foreach ( var vertex in this )
371+ {
372+ foreach ( var edge in Edges ( vertex ) )
373+ {
374+ graph . AddEdge ( vertex , edge ) ;
375+ }
376+ }
377+
378+ return graph ;
379+ }
380+
381+ private class GraphVertex < T > : IGraphVertex < T >
382+ {
383+ Graph < T > graph ;
384+ private int vertexIndex ;
385+ private T vertexKey ;
386+
387+ private int maxSize => graph . maxSize ;
388+ private BitArray [ ] matrix => graph . matrix ;
389+
390+ private Dictionary < T , int > vertexIndices => graph . vertexIndices ;
391+ private Dictionary < int , T > reverseVertexIndices => graph . reverseVertexIndices ;
392+
393+ internal GraphVertex ( Graph < T > graph , T vertexKey )
394+ {
395+ if ( ! graph . vertexIndices . ContainsKey ( vertexKey ) )
396+ {
397+ throw new ArgumentException ( "vertex is not in this graph." ) ;
398+ }
399+
400+ this . graph = graph ;
401+ this . vertexKey = vertexKey ;
402+ this . vertexIndex = graph . vertexIndices [ vertexKey ] ;
403+ }
404+
405+ public T Key => vertexKey ;
406+
407+
408+ IEnumerable < IEdge < T > > IGraphVertex < T > . Edges => graph . Edges ( vertexKey )
409+ . Select ( x => new Edge < T , int > ( graph . vertexObjects [ x ] , 1 ) ) ;
410+
411+ public IEdge < T > GetOutEdge ( IGraphVertex < T > targetVertex )
412+ {
413+ if ( ! vertexIndices . ContainsKey ( targetVertex . Key ) )
414+ {
415+ throw new ArgumentException ( "vertex is not in this graph." ) ;
416+ }
417+
418+ var index = vertexIndices [ targetVertex . Key ] ;
419+ var key = targetVertex as GraphVertex < T > ;
420+ return new Edge < T , int > ( targetVertex , 1 ) ;
421+ }
422+
423+ public IEdge < T > GetEdge ( IGraphVertex < T > targetVertex )
424+ {
425+ if ( ! vertexIndices . ContainsKey ( targetVertex . Key ) )
426+ {
427+ throw new ArgumentException ( "vertex is not in this graph." ) ;
428+ }
429+
430+ var index = vertexIndices [ targetVertex . Key ] ;
431+ var key = targetVertex as GraphVertex < T > ;
432+ return new Edge < T , int > ( targetVertex , 1 ) ;
433+ }
434+ }
312435 }
313436}
0 commit comments