示例#1
0
        public Optional <IEnumerable <WeightedEdge <T> > > FindSpanningTreeEdges(IGraph <T> graph)
        {
            if (graph == null)
            {
                throw new ArgumentNullException(nameof(graph));
            }

            if (graph.Count == 0)
            {
                return(Optional <IEnumerable <WeightedEdge <T> > > .None());
            }

            var source            = _sourceNodeProvider(graph);
            var distances         = InitializeDistanceTable(graph, source);
            var verticesToProcess = new MinBinaryHeap <DistanceInfo <T> >(DistanceInfo <T> .DistanceComparer);
            var processedVertices = new HashSet <T>(graph.Comparer);
            var spanningTree      = new HashSet <WeightedEdge <T> >(WeightedEdge <T> .NonDirectionalComparer(graph.Comparer));

            verticesToProcess.Push(DistanceInfo <T> .Zero(source));

            while (verticesToProcess.Count > 0)
            {
                var currentVertex  = verticesToProcess.Pop().Single().PreviousVertex;
                var sourceDistance = distances[currentVertex];

                processedVertices.Add(currentVertex);

                if (graph.Comparer.Equals(source, currentVertex) == false)
                {
                    var edge = new WeightedEdge <T>(sourceDistance.PreviousVertex, currentVertex, sourceDistance.Distance);
                    if (spanningTree.Contains(edge) == false)
                    {
                        spanningTree.Add(edge);
                    }
                }

                foreach (var destinationVertex in graph.GetAdjacentVertices(currentVertex))
                {
                    if (processedVertices.Contains(destinationVertex))
                    {
                        continue;
                    }

                    var step = StepMetadata <T> .ForSpanningTree(currentVertex, destinationVertex, distances);

                    if (step.FoundShorterDistance())
                    {
                        distances[destinationVertex] = step.ToSource();
                        verticesToProcess.Push(step.ToDestination());
                    }
                }
            }

            return(spanningTree);
        }