/// <summary> /// Topologically sorts the nodes of this graph. Throws an exception if this graph is acyclic. /// </summary> /// <returns>The sorted nodes collection.</returns> public IEnumerable <EdgeListNode <T> > TopologicalSort() { List <EdgeListNode <T> > ordered = new List <EdgeListNode <T> >(); List <EdgeListNode <T> > noIncomingEdges = NodesWithoutIncomingEdges.ToList(); List <Edge <EdgeListNode <T> > > allEdges = AllEdges.ToList(); while (noIncomingEdges.Count() > 0) { EdgeListNode <T> node = noIncomingEdges[0]; noIncomingEdges.RemoveAt(0); ordered.Add(node); IEnumerable <Edge <EdgeListNode <T> > > outgoingEdges = allEdges.Where((Edge <EdgeListNode <T> > e) => e.From.Equals(node)).ToList(); foreach (Edge <EdgeListNode <T> > edge in outgoingEdges) { allEdges.Remove(edge); int index = allEdges.FindIndex((Edge <EdgeListNode <T> > e) => e.To.Equals(edge.To)); if (index == -1) { noIncomingEdges.Add(edge.To); } } } if (allEdges.Count > 0) { throw new Exception("This graph has at least one cycle, so it can't be topologically sorted."); } else { return(ordered); } }
/// <summary> /// Creates an edge to the specified node and stores it in this node edges, if it does not already exist. /// </summary> /// <param name="node">The node on the 'to' end of the edge.</param> /// <returns>The edge between this node and the specified node.</returns> public Edge <EdgeListNode <T> > AddEdgeTo(EdgeListNode <T> node) { Edge <EdgeListNode <T> > newEdge = new Edge <EdgeListNode <T> >(this, node); Edge <EdgeListNode <T> > oldEdge = this.FindEdgeTo(node); Edge <EdgeListNode <T> > actualEdge = oldEdge; if (oldEdge == null) { _edges.Add(newEdge); actualEdge = newEdge; } return(actualEdge); }
/// <summary> /// Adds a new node to this graph, if it does not already exist. /// </summary> /// <param name="node">The node to add.</param> public EdgeListNode <T> AddNode(EdgeListNode <T> node) { EdgeListNode <T> target = FindNode(node.Value); if (target == null) { _nodes.Add(node); return(node); } else { return(target); } }
/// <summary> /// Adds a directed edge between the nodes identified by the specified values. /// </summary> /// <param name="from">Value identifying the node that will spawn the edge.</param> /// <param name="to">Value identifying the node on the 'to' end of the edge.</param> /// <returns>The edge between the targeted nodes.</returns> public Edge <EdgeListNode <T> > AddDirectedEdge(T from, T to) { EdgeListNode <T> fromTarget = FindNode(from); EdgeListNode <T> toTarget = FindNode(to); if (fromTarget == null) { throw new ArgumentException("The 'from' node is not part of this graph."); } if (toTarget == null) { throw new ArgumentException("The 'to' node is not part of this graph."); } return(fromTarget.AddEdgeTo(to)); }
/// <summary> /// Adds a directed edge between the specified nodes. /// </summary> /// <param name="from">The node spawning the edge.</param> /// <param name="to">The destination of the edge.</param> /// <returns>The edge between the nodes equivalent to the specified nodes.</returns> public Edge <EdgeListNode <T> > AddDirectedEdge(EdgeListNode <T> from, EdgeListNode <T> to) { return(this.AddDirectedEdge(from.Value, to.Value)); }
/// <summary> /// Gets whether this graph contains a node equivalent to the specified node. /// </summary> /// <param name="node">The equivalent node to search for.</param> /// <returns>True if a node is found, false otherwise.</returns> public bool ContainsNode(EdgeListNode <T> node) { return(this.ContainsNode(node.Value)); }
/// <summary> /// Finds a node equivalent to the specified node. /// </summary> /// <param name="node">The node to search for.</param> /// <returns>The node if it is found, null otherwise.</returns> public EdgeListNode <T> FindNode(EdgeListNode <T> node) { return(this.FindNode(node.Value)); }
/// <summary> /// Adds a new node having the specified value as value, if it does not already exist. /// </summary> /// <param name="value"></param> public EdgeListNode <T> AddNode(T value) { EdgeListNode <T> target = new EdgeListNode <T>(value); return(AddNode(target)); }
/// <summary> /// Creates an edge to a node having the specified value and stores it in this node edges, if it does not already exist. /// </summary> /// <param name="value">The value of the node on the 'to' end of the edge.</param> /// /// <returns>The edge between this node and the one having value as the specified value.</returns> public Edge <EdgeListNode <T> > AddEdgeTo(T value) { EdgeListNode <T> newNode = new EdgeListNode <T>(value); return(this.AddEdgeTo(newNode)); }
/// <summary> /// Gets whether this node has an edge going to a node equivalent to the specified node. /// </summary> /// <param name="node">The node on the 'to' end.</param> /// <returns>True if the condition is met, false otherwise.</returns> public bool HasEdgeTo(EdgeListNode <T> node) { return(this.FindEdgeTo(node) != null); }
/// <summary> /// Searches for an edge spawning from this node and ending in a node equivalent to the specified node. /// </summary> /// <param name="node"></param> /// <returns></returns> public Edge <EdgeListNode <T> > FindEdgeTo(EdgeListNode <T> node) { return(this.FindEdgeTo(node.Value)); }