Beispiel #1
0
        /// <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);
            }
        }
Beispiel #2
0
        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);
            }
        }
Beispiel #3
0
            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);
            }
Beispiel #4
0
            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);
            }
Beispiel #5
0
        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);
            }
Beispiel #6
0
 public ReadOnlyKeyedCollection([NotNull] KeyedCollection <TKey, TValue> collection)
 {
     Collection = collection;
 }