/// <inheritdoc /> public override void AddEdge(T from, T to, TWeight weight) { if (!ContainsKey(from)) { throw new KeyNotFoundException(nameof(from) + " value is not found."); } if (!ContainsKey(to)) { throw new KeyNotFoundException(nameof(to) + " value is not found."); } KeyedCollection <T, GraphEdge <T, TWeight> > fromEdges = this[from]; if (fromEdges == null) { fromEdges = MakeContainer(); this[from] = fromEdges; } if (fromEdges.TryGetValue(to, out GraphEdge <T, TWeight> fromEdge)) { if (fromEdge.Weight.CompareTo(weight) > 0) { fromEdge.Weight = weight; } } else { fromEdge = new GraphEdge <T, TWeight>(to, weight); fromEdges.Add(fromEdge); } }
public void AddEdge([NotNull] T from, [NotNull] T to, TWeight weight, bool undirected) { if (!ContainsKey(from)) { throw new KeyNotFoundException(nameof(from) + " value is not found."); } if (!ContainsKey(to)) { throw new KeyNotFoundException(nameof(to) + " value is not found."); } KeyedCollection <T, GraphEdge <T, TWeight> > fromEdges = this[from]; if (fromEdges == null) { fromEdges = MakeContainer(); this[from] = fromEdges; } if (fromEdges.TryGetValue(to, out GraphEdge <T, TWeight> fromEdge)) { if (fromEdge.Weight.CompareTo(weight) > 0) { fromEdge.Weight = weight; } } else { fromEdge = new GraphEdge <T, TWeight>(to, weight); fromEdges.Add(fromEdge); } // short-circuit - loop edge if (!undirected || Comparer.Equals(from, to)) { return; } KeyedCollection <T, GraphEdge <T, TWeight> > toEdges = this[to]; if (toEdges == null) { toEdges = MakeContainer(); this[to] = toEdges; } if (toEdges.TryGetValue(from, out GraphEdge <T, TWeight> toEdge)) { if (toEdge.Weight.CompareTo(weight) > 0) { toEdge.Weight = weight; } } else { toEdge = new GraphEdge <T, TWeight>(from, weight); toEdges.Add(toEdge); } }
public bool MoveNext() { if (_version != _graph._version) { throw new VersionChangedException(); } if (_done) { return(false); } if (!_started) { _started = true; foreach (T vertex in _graph.Keys) { _queue.Enqueue(vertex); } } // visit the next queued edge if (_edges.Count > 0) { _current = _edges.Dequeue(); return(true); } // no more vertices to explore if (_queue.Count == 0) { _done = true; return(false); } // Queue the next edges while (_queue.Count > 0) { T from = _queue.Dequeue(); KeyedCollection <T, GraphEdge <T, TWeight> > edges = _graph[from]; if (edges == null || edges.Count == 0) { continue; } foreach (GraphEdge <T, TWeight> edge in edges) { _edges.Enqueue(new EdgeEntry <T, GraphEdge <T, TWeight> >(from, edge)); } _current = _edges.Dequeue(); if (_edges.Count > 0) { break; } } return(true); }
public bool MoveNext() { if (_version != _graph._version) { throw new VersionChangedException(); } if (_done) { return(false); } if (!_started) { _started = true; // Start at the root _stack.Push(_root); } // visit the next queued edge do { _hasValue = _stack.Count > 0; _current = _hasValue ? _stack.Pop() : default(T); }while (_hasValue && _visited.Contains(_current)); if (!_hasValue || _current == null /* just for R# */) { _done = true; return(false); } _visited.Add(_current); // Queue the next vertices KeyedCollection <T, GraphEdge <T, TWeight> > edges = _graph[_current]; if (edges == null || edges.Count == 0) { return(true); } foreach (GraphEdge <T, TWeight> edge in edges) { _stack.Push(edge.To); } return(true); }
public IEnumerable <T> TopologicalSort() { // Udemy - Code With Mosh - Data Structures & Algorithms - Part 2 if (Count == 0) { return(Enumerable.Empty <T>()); } // for detecting cycles bool conflictIsSet = false; T conflictVertex = default(T); HashSet <T> visitedSet = new HashSet <T>(Comparer); Stack <T> resultStack = new Stack <T>(Count); int graphVersion = _version; foreach (T vertex in Keys) { if (graphVersion != _version) { throw new VersionChangedException(); } if (visitedSet.Contains(vertex) || TopologicalSortLocal(vertex, vertex, visitedSet, resultStack, graphVersion, ref conflictVertex, ref conflictIsSet)) { continue; } // cycle detected throw new Exception($"Cycle detected [{string.Join(", ", visitedSet.Append(conflictVertex))}]"); } return(resultStack); bool TopologicalSortLocal(T vertex, T parent, HashSet <T> visited, Stack <T> result, int version, ref T conflict, ref bool conflictSet) { if (version != _version) { throw new VersionChangedException(); } if (visited.Contains(vertex)) { return(true); } visited.Add(vertex); result.Push(vertex); KeyedCollection <T, GraphEdge <T, TWeight> > edges = this[vertex]; if (edges is { Count : > 0 }) { foreach (GraphEdge <T, TWeight> edge in edges.Values.OrderBy(e => e.Weight)) { if (IsLoop(parent, edge) || IsLoop(vertex, edge)) { continue; } if (visited.Contains(edge.To) /* cycle detected */ || !TopologicalSortLocal(edge.To, vertex, visited, result, version, ref conflict, ref conflictSet)) { if (!conflictSet) { conflictSet = true; conflict = edge.To; } return(false); } } } return(true); }
public ReadOnlyKeyedCollection([NotNull] KeyedCollection <TKey, TValue> collection) { Collection = collection; }