private void ComputeLevels() { if (!this._isDirty) { return; } this.ReinitializeKeys(); // find the deepest node var orderedNodes = this.Sort(); var deepestNode = new InternalNodeFast <T>(default(T), null) { ReferenceRelativeLevel = int.MinValue }; foreach (InternalNodeFast <T> node in orderedNodes) { node.ReferenceRelativeLevel = GetMaxLevel(node.Parents) + 1; if (node.ReferenceRelativeLevel > deepestNode.ReferenceRelativeLevel) { deepestNode = node; } } var referenceNode = deepestNode; this.ReferencePoint = 0; // go up and compute levels of parent nodes. int minLevel = this.VisitRelations(referenceNode); this.ReferencePoint = minLevel * (-1); this._countLevels = deepestNode.Level + 1; this._isDirty = false; }
private void AddEdge(InternalNodeFast <T> source, InternalNodeFast <T> destination) { if (source.Edges.Count(_ => _ == destination) == 0) { source.Edges.Add(destination); } if (destination.Parents.Count(_ => _ == source) == 0) { destination.Parents.Add(source); // try to move inside the previous if } }
private InternalNodeFast <T> GetOrCreateNode(T publicNode) { InternalNodeFast <T> node; if (!_nodes.TryGetValue(publicNode, out node)) { node = new InternalNodeFast <T>(publicNode, this); _nodes.Add(publicNode, node); } return(node); }
private int VisitRelations(InternalNodeFast <T> startNode) { int minLevel = int.MaxValue; var stack = new Stack <InternalNodeFast <T> >(); var visitedNodes = new bool[_nodes.Count]; stack.Push(startNode); while (stack.Count != 0) { var node = stack.Pop(); visitedNodes[node.Key] = true; if (node.ReferenceRelativeLevel < minLevel) { minLevel = node.ReferenceRelativeLevel; } foreach (var parent in node.Parents) { if (visitedNodes[parent.Key]) { continue; } parent.ReferenceRelativeLevel = node.ReferenceRelativeLevel - 1; stack.Push(parent); } foreach (var child in node.Edges) { if (visitedNodes[child.Key]) { continue; } child.ReferenceRelativeLevel = node.ReferenceRelativeLevel + 1; stack.Push(child); } } return(minLevel); }
/// <summary> /// Creates temporary light-weight copy which is used by CanSort(sequence) method /// </summary> /// <param name="initialGraph"></param> private GraphFast(GraphFast <T> initialGraph) : this(initialGraph.CountNodes) { if (initialGraph._isDirty) { initialGraph.ReinitializeKeys(); } var nodeKeys = new InternalNodeFast <T> [initialGraph.CountNodes]; foreach (var node in initialGraph._nodes) { nodeKeys[node.Value.Key] = new InternalNodeFast <T>(node.Value.Value, this, node.Value.Key); this._nodes[node.Key] = node.Value; } foreach (var node in initialGraph._nodes.Values) { foreach (var edge in node.Edges) { nodeKeys[node.Key].Edges.Add(nodeKeys[edge.Key]); } } }