5
5
6
6
namespace Advanced . Algorithms . DataStructures . Graph . AdjacencyMatrix
7
7
{
8
-
9
8
/// <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.
11
10
/// IEnumerable enumerates all vertices.
12
11
/// </summary>
13
- public class Graph < T > : IEnumerable < T >
12
+ public class Graph < T > : IGraph < T > , IEnumerable < T >
14
13
{
15
- public int VerticesCount => usedSize ;
14
+ private BitArray [ ] matrix ;
16
15
17
16
private Dictionary < T , int > vertexIndices ;
18
17
private Dictionary < int , T > reverseVertexIndices ;
18
+ private Dictionary < T , GraphVertex < T > > vertexObjects ;
19
19
20
- private BitArray [ ] matrix ;
21
-
22
- private int maxSize ;
20
+ private int maxSize => matrix . Length ;
23
21
private int usedSize ;
24
22
private int nextAvailableIndex ;
25
23
24
+ public int VerticesCount => usedSize ;
25
+ public bool IsWeightedGraph => false ;
26
+
26
27
public Graph ( )
27
28
{
28
- maxSize = 1 ;
29
29
vertexIndices = new Dictionary < T , int > ( ) ;
30
30
reverseVertexIndices = new Dictionary < int , T > ( ) ;
31
- matrix = new BitArray [ maxSize ] ;
31
+ vertexObjects = new Dictionary < T , GraphVertex < T > > ( ) ;
32
+
33
+ matrix = new BitArray [ 1 ] ;
32
34
33
35
for ( int i = 0 ; i < maxSize ; i ++ )
34
36
{
35
37
matrix [ i ] = new BitArray ( maxSize ) ;
36
38
}
37
39
}
38
40
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
+
39
52
/// <summary>
40
53
/// Add a new vertex to this graph.
41
54
/// Time complexity: O(1).
@@ -64,6 +77,7 @@ public void AddVertex(T value)
64
77
65
78
vertexIndices . Add ( value , nextAvailableIndex ) ;
66
79
reverseVertexIndices . Add ( nextAvailableIndex , value ) ;
80
+ vertexObjects . Add ( value , new GraphVertex < T > ( this , value ) ) ;
67
81
68
82
nextAvailableIndex ++ ;
69
83
usedSize ++ ;
@@ -103,6 +117,7 @@ public void RemoveVertex(T value)
103
117
104
118
reverseVertexIndices . Remove ( index ) ;
105
119
vertexIndices . Remove ( value ) ;
120
+ vertexObjects . Remove ( value ) ;
106
121
107
122
usedSize -- ;
108
123
@@ -199,19 +214,37 @@ public IEnumerable<T> Edges(T vertex)
199
214
200
215
var index = vertexIndices [ vertex ] ;
201
216
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 ] ;
203
235
204
236
for ( int i = 0 ; i < maxSize ; i ++ )
205
237
{
206
238
if ( matrix [ i ] . Get ( index ) )
207
239
{
208
- result . Add ( reverseVertexIndices [ i ] ) ;
240
+ count ++ ;
209
241
}
210
242
}
211
243
212
- return result ;
244
+ return count ;
213
245
}
214
246
247
+
215
248
private void doubleMatrixSize ( )
216
249
{
217
250
var newMatrix = new BitArray [ maxSize * 2 ] ;
@@ -237,7 +270,7 @@ private void doubleMatrixSize()
237
270
{
238
271
for ( int j = i ; j < maxSize ; j ++ )
239
272
{
240
- if ( matrix [ i ] . Get ( j ) && matrix [ j ] . Get ( i )
273
+ if ( matrix [ i ] . Get ( j ) && matrix [ j ] . Get ( i )
241
274
&& reverseVertexIndices . ContainsKey ( i )
242
275
&& reverseVertexIndices . ContainsKey ( j ) )
243
276
{
@@ -253,7 +286,6 @@ private void doubleMatrixSize()
253
286
matrix = newMatrix ;
254
287
vertexIndices = newVertexIndices ;
255
288
reverseVertexIndices = newReverseIndices ;
256
- maxSize *= 2 ;
257
289
}
258
290
259
291
private void halfMatrixSize ( )
@@ -281,7 +313,7 @@ private void halfMatrixSize()
281
313
{
282
314
for ( int j = i ; j < maxSize ; j ++ )
283
315
{
284
- if ( matrix [ i ] . Get ( j ) && matrix [ j ] . Get ( i )
316
+ if ( matrix [ i ] . Get ( j ) && matrix [ j ] . Get ( i )
285
317
&& reverseVertexIndices . ContainsKey ( i )
286
318
&& reverseVertexIndices . ContainsKey ( j ) )
287
319
{
@@ -297,9 +329,10 @@ private void halfMatrixSize()
297
329
matrix = newMatrix ;
298
330
vertexIndices = newVertexIndices ;
299
331
reverseVertexIndices = newReverseIndices ;
300
- maxSize /= 2 ;
301
332
}
302
333
334
+ public IEnumerable < IGraphVertex < T > > VerticesAsEnumberable => vertexObjects . Select ( x => x . Value ) ;
335
+
303
336
IEnumerator IEnumerable . GetEnumerator ( )
304
337
{
305
338
return GetEnumerator ( ) ;
@@ -309,5 +342,95 @@ public IEnumerator<T> GetEnumerator()
309
342
{
310
343
return vertexIndices . Select ( x => x . Key ) . GetEnumerator ( ) ;
311
344
}
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
+ }
312
435
}
313
436
}
0 commit comments