using System.Collections; using System.Collections.Generic; using System; namespace Rokojori { public abstract class GraphWalker where N:class { public virtual int NumConnectedFrom( N node ){ return 0;} public virtual N GetConnectedFrom( N node, int index ){ return default(N);} public abstract int NumConnectedTo( N node ); public abstract N GetConnectedTo( N node, int index ); public int NumConnectedAll( N node ) { return NumConnectedTo( node ) + NumConnectedFrom( node ); } public N GetConnected( N node, int index ) { var fromConnections = NumConnectedFrom( node ); return index < fromConnections ? GetConnectedFrom( node, index ) : GetConnectedTo( node, index - fromConnections ); } public bool IsConnectedTo( N source, N destination ) { var processed = new HashSet(); var toDo = new List(); toDo.Add( source ); while ( toDo.Count > 0 ) { var current = Lists.RemoveFirst( toDo ); if ( processed.Contains( current ) ) { continue; } processed.Add( current ); var numConnected = NumConnectedTo( current ); for ( int i = 0; i < numConnected; i++ ) { var connected = GetConnected( current, i ); if ( connected == destination ) { return true; } if ( ! processed.Contains( connected ) ) { toDo.Add( connected ); } } } return false; } public bool IsDirectlyConnectedTo( N node, N other ) { if ( node == null || other == null ) { return false; } var connected = NumConnectedTo( node ); for ( int i = 0; i < connected; i++ ) { if ( GetConnected( node, i ) == other ) { return true; } } return false; } public List ComputeOrder( List nodes ) { var processed = new HashSet(); var unprocessed = nodes.Clone(); var order = new List(); while ( unprocessed.Count > 0 ) { var itemIndex = -1; for ( int i = 0; itemIndex == -1 && i < unprocessed.Count; i++ ) { if ( CanProcess( unprocessed[ i ], processed ) ) { itemIndex = i; } } if ( itemIndex == -1 ) { order.AddRange( unprocessed ); return order; } var item = unprocessed[ itemIndex ]; unprocessed.RemoveAt( itemIndex ); processed.Add( item ); order.Add( item ); } return order; } bool CanProcess( N n, HashSet processed ) { var dependencies = NumConnectedFrom( n ); for ( int i = 0 ; i < dependencies; i++ ) { var connected = GetConnectedFrom( n, i ); if ( ! processed.Contains( connected ) ) { return false; } } return true; } } }