@@ -3555,4 +3555,130 @@ public object VisitUsingExpression(UsingExpressionAst usingExpressionAst)
35553555 return null ;
35563556 }
35573557 }
3558+
3559+ /// Class to represent a directed graph
3560+ public class Digraph < T >
3561+ {
3562+ public int NumVertices
3563+ {
3564+ get { return graph . Count ; }
3565+ }
3566+
3567+ private List < List < int > > graph ;
3568+ private Dictionary < T , int > vertexIndexMap ;
3569+
3570+
3571+ private int GetIndex ( T vertex )
3572+ {
3573+ int idx ;
3574+ return vertexIndexMap . TryGetValue ( vertex , out idx ) ? idx : - 1 ;
3575+ }
3576+
3577+ public IEnumerable < T > GetNeighbors ( T vertex )
3578+ {
3579+ ValidateVertexArgument ( vertex ) ;
3580+ var idx = GetIndex ( vertex ) ;
3581+ var idxVertexMap = vertexIndexMap . ToDictionary ( x => x . Value , x => x . Key ) ;
3582+ foreach ( var neighbor in graph [ idx ] )
3583+ {
3584+ yield return idxVertexMap [ neighbor ] ;
3585+ }
3586+ }
3587+
3588+ public int GetNumNeighbors ( T vertex )
3589+ {
3590+ ValidateVertexArgument ( vertex ) ;
3591+ return graph [ GetIndex ( vertex ) ] . Count ;
3592+ }
3593+
3594+ public Digraph ( )
3595+ {
3596+ graph = new List < List < int > > ( ) ;
3597+ vertexIndexMap = new Dictionary < T , int > ( ) ;
3598+ }
3599+
3600+ public void AddVertex ( T vertex )
3601+ {
3602+ if ( vertex == null )
3603+ {
3604+ throw new ArgumentNullException ( "vertex" ) ;
3605+ }
3606+
3607+ if ( GetIndex ( vertex ) != - 1 )
3608+ {
3609+ throw new ArgumentException ( "Vertex already present! Cannot add it to the Digraph" , "vertex" ) ;
3610+ }
3611+
3612+ vertexIndexMap . Add ( vertex , graph . Count ) ;
3613+ graph . Add ( new List < int > ( ) ) ;
3614+ }
3615+
3616+ public void AddEdge ( T fromVertex , T toVertex )
3617+ {
3618+ ValidateVertexArgument ( fromVertex ) ;
3619+ ValidateVertexArgument ( toVertex ) ;
3620+
3621+ var toIdx = GetIndex ( toVertex ) ;
3622+ var fromVertexList = graph [ GetIndex ( fromVertex ) ] ;
3623+ if ( ! fromVertexList . Contains ( toIdx ) )
3624+ {
3625+ fromVertexList . Add ( toIdx ) ;
3626+ }
3627+ }
3628+
3629+ public bool IsConnected ( T vertex1 , T vertex2 )
3630+ {
3631+ ValidateVertexArgument ( vertex1 ) ;
3632+ ValidateVertexArgument ( vertex2 ) ;
3633+ var visited = new bool [ graph . Count ] ;
3634+ return IsConnected ( GetIndex ( vertex1 ) , GetIndex ( vertex2 ) , ref visited ) ;
3635+ }
3636+
3637+ private bool IsConnected ( int fromIdx , int toIdx , ref bool [ ] visited )
3638+ {
3639+ visited [ fromIdx ] = true ;
3640+ if ( fromIdx == toIdx )
3641+ {
3642+ return true ;
3643+ }
3644+
3645+ bool isConnected = false ;
3646+ foreach ( var vertexIdx in graph [ fromIdx ] )
3647+ {
3648+ if ( ! visited [ vertexIdx ] )
3649+ {
3650+ isConnected |= IsConnected ( vertexIdx , toIdx , ref visited ) ;
3651+ }
3652+
3653+ if ( isConnected ) // no need to search further
3654+ {
3655+ break ;
3656+ }
3657+ }
3658+
3659+ return isConnected ;
3660+ }
3661+
3662+ private void ValidateNotNull ( T vertex )
3663+ {
3664+ if ( vertex == null )
3665+ {
3666+ throw new ArgumentNullException ( "vertex" ) ;
3667+ }
3668+ }
3669+
3670+ private void ValidateVertexPresence ( T vertex )
3671+ {
3672+ if ( GetIndex ( vertex ) == - 1 )
3673+ {
3674+ throw new ArgumentOutOfRangeException ( "vertex not present in the Digraph." , "vertex" ) ;
3675+ }
3676+ }
3677+
3678+ private void ValidateVertexArgument ( T vertex )
3679+ {
3680+ ValidateNotNull ( vertex ) ;
3681+ ValidateVertexPresence ( vertex ) ;
3682+ }
3683+ }
35583684}
0 commit comments