@@ -9,25 +9,49 @@ namespace Advanced.Algorithms.DataStructures.Graph.AdjacencyMatrix
99 /// A weighted graph implementation using dynamically growinng/shrinking adjacency matrix array.
1010 /// IEnumerable enumerates all vertices.
1111 /// </summary>
12- public class WeightedDiGraph < T , TW > : IEnumerable < T > where TW : IComparable
12+ public class WeightedDiGraph < T , TW > : IDiGraph < T > , IGraph < T > , IEnumerable < T > where TW : IComparable
1313 {
14- public int VerticesCount => usedSize ;
14+ public int VerticesCount { get ; private set ; }
1515
1616 private Dictionary < T , int > vertexIndices ;
1717 private Dictionary < int , T > reverseVertexIndices ;
18+ private Dictionary < T , WeightedDiGraphVertex < T , TW > > vertexObjects ;
1819
1920 private TW [ , ] matrix ;
21+ private int maxSize => matrix . GetLength ( 0 ) ;
22+
23+ public bool IsWeightedGraph => true ;
2024
21- private int maxSize ;
22- private int usedSize ;
2325 private int nextAvailableIndex ;
2426
2527 public WeightedDiGraph ( )
2628 {
27- maxSize = 1 ;
2829 vertexIndices = new Dictionary < T , int > ( ) ;
2930 reverseVertexIndices = new Dictionary < int , T > ( ) ;
30- matrix = new TW [ maxSize , maxSize ] ;
31+ vertexObjects = new Dictionary < T , WeightedDiGraphVertex < T , TW > > ( ) ;
32+
33+ matrix = new TW [ 1 , 1 ] ;
34+ }
35+
36+ public IDiGraphVertex < T > ReferenceVertex => getReferenceVertex ( ) ;
37+ IGraphVertex < T > IGraph < T > . ReferenceVertex => getReferenceVertex ( ) ;
38+
39+ private WeightedDiGraphVertex < T , TW > getReferenceVertex ( )
40+ {
41+ if ( this . VerticesCount == 0 )
42+ {
43+ throw new Exception ( "Empty graph." ) ;
44+ }
45+
46+ return vertexObjects [ this . First ( ) ] ;
47+ }
48+
49+ public IEnumerable < IDiGraphVertex < T > > VerticesAsEnumberable => getVerticesAsEnumerable ( ) ;
50+ IEnumerable < IGraphVertex < T > > IGraph < T > . VerticesAsEnumberable => getVerticesAsEnumerable ( ) ;
51+
52+ private IEnumerable < WeightedDiGraphVertex < T , TW > > getVerticesAsEnumerable ( )
53+ {
54+ return this . Select ( x => vertexObjects [ x ] ) ;
3155 }
3256
3357 /// <summary>
@@ -46,7 +70,7 @@ public void AddVertex(T value)
4670 throw new Exception ( "Vertex exists." ) ;
4771 }
4872
49- if ( usedSize < maxSize / 2 )
73+ if ( VerticesCount < maxSize / 2 )
5074 {
5175 halfMatrixSize ( ) ;
5276 }
@@ -58,8 +82,9 @@ public void AddVertex(T value)
5882
5983 vertexIndices . Add ( value , nextAvailableIndex ) ;
6084 reverseVertexIndices . Add ( nextAvailableIndex , value ) ;
85+ vertexObjects . Add ( value , new WeightedDiGraphVertex < T , TW > ( this , value ) ) ;
6186 nextAvailableIndex ++ ;
62- usedSize ++ ;
87+ VerticesCount ++ ;
6388
6489 }
6590
@@ -79,13 +104,13 @@ public void RemoveVertex(T value)
79104 throw new Exception ( "Vertex does'nt exist." ) ;
80105 }
81106
82- if ( usedSize <= maxSize / 2 )
107+ if ( VerticesCount <= maxSize / 2 )
83108 {
84109 halfMatrixSize ( ) ;
85110 }
86111
87112 var index = vertexIndices [ value ] ;
88-
113+
89114 //clear edges
90115 for ( int i = 0 ; i < maxSize ; i ++ )
91116 {
@@ -95,8 +120,8 @@ public void RemoveVertex(T value)
95120
96121 reverseVertexIndices . Remove ( index ) ;
97122 vertexIndices . Remove ( value ) ;
98-
99- usedSize -- ;
123+ vertexObjects . Remove ( value ) ;
124+ VerticesCount -- ;
100125
101126 }
102127
@@ -184,7 +209,7 @@ public bool HasEdge(T source, T dest)
184209 return false ;
185210 }
186211
187- public IEnumerable < Tuple < T , TW > > OutEdges ( T vertex )
212+ public int OutEdgeCount ( T vertex )
188213 {
189214 if ( ! vertexIndices . ContainsKey ( vertex ) )
190215 {
@@ -193,20 +218,20 @@ public IEnumerable<Tuple<T, TW>> OutEdges(T vertex)
193218
194219 var index = vertexIndices [ vertex ] ;
195220
196- var result = new List < Tuple < T , TW > > ( ) ;
221+ int count = 0 ;
197222
198223 for ( int i = 0 ; i < maxSize ; i ++ )
199224 {
200- if ( ! matrix [ index , i ] . Equals ( default ( TW ) ) )
225+ if ( ! matrix [ index , i ] . Equals ( default ( TW ) ) )
201226 {
202- result . Add ( new Tuple < T , TW > ( reverseVertexIndices [ i ] , matrix [ index , i ] ) ) ;
227+ count ++ ;
203228 }
204229 }
205230
206- return result ;
231+ return count ;
207232 }
208233
209- public IEnumerable < Tuple < T , TW > > InEdges ( T vertex )
234+ public IEnumerable < KeyValuePair < T , TW > > OutEdges ( T vertex )
210235 {
211236 if ( ! vertexIndices . ContainsKey ( vertex ) )
212237 {
@@ -217,15 +242,55 @@ public IEnumerable<Tuple<T, TW>> InEdges(T vertex)
217242
218243 var result = new List < Tuple < T , TW > > ( ) ;
219244
245+ for ( int i = 0 ; i < maxSize ; i ++ )
246+ {
247+ if ( ! matrix [ index , i ] . Equals ( default ( TW ) ) )
248+ {
249+ yield return new KeyValuePair < T , TW > ( reverseVertexIndices [ i ] , matrix [ index , i ] ) ;
250+ }
251+ }
252+ }
253+
254+ public int InEdgeCount ( T vertex )
255+ {
256+ if ( ! vertexIndices . ContainsKey ( vertex ) )
257+ {
258+ throw new ArgumentException ( "vertex is not in this graph." ) ;
259+ }
260+
261+ var index = vertexIndices [ vertex ] ;
262+
263+ int count = 0 ;
264+
220265 for ( int i = 0 ; i < maxSize ; i ++ )
221266 {
222267 if ( ! matrix [ i , index ] . Equals ( default ( TW ) ) )
223268 {
224- result . Add ( new Tuple < T , TW > ( reverseVertexIndices [ i ] , matrix [ i , index ] ) ) ;
269+ count ++ ;
225270 }
226271 }
227272
228- return result ;
273+ return count ;
274+ }
275+
276+ public IEnumerable < KeyValuePair < T , TW > > InEdges ( T vertex )
277+ {
278+ if ( ! vertexIndices . ContainsKey ( vertex ) )
279+ {
280+ throw new ArgumentException ( "vertex is not in this graph." ) ;
281+ }
282+
283+ var index = vertexIndices [ vertex ] ;
284+
285+ var result = new List < Tuple < T , TW > > ( ) ;
286+
287+ for ( int i = 0 ; i < maxSize ; i ++ )
288+ {
289+ if ( ! matrix [ i , index ] . Equals ( default ( TW ) ) )
290+ {
291+ yield return new KeyValuePair < T , TW > ( reverseVertexIndices [ i ] , matrix [ i , index ] ) ;
292+ }
293+ }
229294 }
230295
231296 private void doubleMatrixSize ( )
@@ -248,7 +313,7 @@ private void doubleMatrixSize()
248313 {
249314 for ( int j = 0 ; j < maxSize ; j ++ )
250315 {
251- if ( ! matrix [ i , j ] . Equals ( default ( TW ) )
316+ if ( ! matrix [ i , j ] . Equals ( default ( TW ) )
252317 && reverseVertexIndices . ContainsKey ( i )
253318 && reverseVertexIndices . ContainsKey ( j ) )
254319 {
@@ -263,7 +328,7 @@ private void doubleMatrixSize()
263328 matrix = newMatrix ;
264329 vertexIndices = newVertexIndices ;
265330 reverseVertexIndices = newReverseIndices ;
266- maxSize *= 2 ;
331+
267332 }
268333
269334 private void halfMatrixSize ( )
@@ -286,7 +351,7 @@ private void halfMatrixSize()
286351 {
287352 for ( int j = 0 ; j < maxSize ; j ++ )
288353 {
289- if ( ! matrix [ i , j ] . Equals ( default ( TW ) )
354+ if ( ! matrix [ i , j ] . Equals ( default ( TW ) )
290355 && reverseVertexIndices . ContainsKey ( i )
291356 && reverseVertexIndices . ContainsKey ( j ) )
292357 {
@@ -301,7 +366,6 @@ private void halfMatrixSize()
301366 matrix = newMatrix ;
302367 vertexIndices = newVertexIndices ;
303368 reverseVertexIndices = newReverseIndices ;
304- maxSize /= 2 ;
305369 }
306370
307371 IEnumerator IEnumerable . GetEnumerator ( )
@@ -313,5 +377,122 @@ public IEnumerator<T> GetEnumerator()
313377 {
314378 return vertexIndices . Select ( x => x . Key ) . GetEnumerator ( ) ;
315379 }
380+
381+ public bool ContainsVertex ( T value )
382+ {
383+ return vertexIndices . ContainsKey ( value ) ;
384+ }
385+
386+ public IDiGraphVertex < T > GetVertex ( T key )
387+ {
388+ return vertexObjects [ key ] ;
389+ }
390+
391+ IGraphVertex < T > IGraph < T > . GetVertex ( T key )
392+ {
393+ return vertexObjects [ key ] ;
394+ }
395+
396+ IDiGraph < T > IDiGraph < T > . Clone ( )
397+ {
398+ return Clone ( ) ;
399+ }
400+
401+ IGraph < T > IGraph < T > . Clone ( )
402+ {
403+ return Clone ( ) ;
404+ }
405+
406+ public WeightedDiGraph < T , TW > Clone ( )
407+ {
408+ var graph = new WeightedDiGraph < T , TW > ( ) ;
409+
410+ foreach ( var vertex in this )
411+ {
412+ graph . AddVertex ( vertex ) ;
413+ }
414+
415+ foreach ( var vertex in this )
416+ {
417+ foreach ( var edge in OutEdges ( vertex ) )
418+ {
419+ graph . AddEdge ( vertex , edge . Key , edge . Value ) ;
420+ }
421+ }
422+
423+ return graph ;
424+ }
425+
426+ /// <summary>
427+ /// IEnumerable enumerates all the outgoing edge destination vertices.
428+ /// </summary>
429+ private class WeightedDiGraphVertex < T , TW > : IDiGraphVertex < T > , IGraphVertex < T > where TW : IComparable
430+ {
431+ WeightedDiGraph < T , TW > graph ;
432+ private int vertexIndex ;
433+ private T vertexKey ;
434+
435+ private int maxSize => graph . maxSize ;
436+ private TW [ , ] matrix => graph . matrix ;
437+
438+ private Dictionary < T , int > vertexIndices => graph . vertexIndices ;
439+ private Dictionary < int , T > reverseVertexIndices => graph . reverseVertexIndices ;
440+
441+ internal WeightedDiGraphVertex ( WeightedDiGraph < T , TW > graph , T vertexKey )
442+ {
443+ if ( ! graph . vertexIndices . ContainsKey ( vertexKey ) )
444+ {
445+ throw new ArgumentException ( "vertex is not in this graph." ) ;
446+ }
447+
448+ this . graph = graph ;
449+ this . vertexKey = vertexKey ;
450+ this . vertexIndex = graph . vertexIndices [ vertexKey ] ;
451+ }
452+
453+ public T Key => vertexKey ;
454+
455+ IEnumerable < IDiEdge < T > > IDiGraphVertex < T > . OutEdges => OutEdges ( )
456+ . Select ( x => new DiEdge < T , TW > ( graph . vertexObjects [ x . Key ] , x . Value ) ) ;
457+
458+ IEnumerable < IDiEdge < T > > IDiGraphVertex < T > . InEdges => InEdges ( )
459+ . Select ( x => new DiEdge < T , TW > ( graph . vertexObjects [ x . Key ] , x . Value ) ) ;
460+
461+ IEnumerable < IEdge < T > > IGraphVertex < T > . Edges => OutEdges ( )
462+ . Select ( x => new Edge < T , TW > ( graph . vertexObjects [ x . Key ] , x . Value ) ) ;
463+
464+ public int OutEdgeCount => graph . OutEdgeCount ( vertexKey ) ;
465+ public int InEdgeCount => graph . InEdgeCount ( vertexKey ) ;
466+
467+ public IEnumerable < KeyValuePair < T , TW > > OutEdges ( ) => graph . OutEdges ( vertexKey ) ;
468+ public IEnumerable < KeyValuePair < T , TW > > InEdges ( ) => graph . InEdges ( vertexKey ) ;
469+
470+ public IDiEdge < T > GetOutEdge ( IDiGraphVertex < T > targetVertex )
471+ {
472+ if ( ! vertexIndices . ContainsKey ( targetVertex . Key ) )
473+ {
474+ throw new ArgumentException ( "vertex is not in this graph." ) ;
475+ }
476+
477+ var index = vertexIndices [ targetVertex . Key ] ;
478+ var key = targetVertex as WeightedDiGraphVertex < T , TW > ;
479+ return new DiEdge < T , TW > ( targetVertex , matrix [ vertexIndex , index ] ) ;
480+ }
481+
482+ public IEdge < T > GetEdge ( IGraphVertex < T > targetVertex )
483+ {
484+ if ( ! vertexIndices . ContainsKey ( targetVertex . Key ) )
485+ {
486+ throw new ArgumentException ( "vertex is not in this graph." ) ;
487+ }
488+
489+ var index = vertexIndices [ targetVertex . Key ] ;
490+ var key = targetVertex as WeightedDiGraphVertex < T , TW > ;
491+ return new Edge < T , TW > ( targetVertex , matrix [ vertexIndex , index ] ) ;
492+ }
493+
494+ }
316495 }
496+
497+
317498}
0 commit comments