コード例 #1
0
        /// <summary>
        ///  Uses Prim's algorithm to build an MST spanning the mstNodes.
        ///  O(|mstNodes|^2) runtime.
        /// </summary>
        /// <param name="startFrom">A GraphNode to start from.</param>
        public void Span(GraphNode startFrom)
        {
            var adjacentEdgeQueue = new LinkedListPriorityQueue <LinkedGraphEdge>(100);

            var startIndex = startFrom.DistancesIndex;
            // All nodes that are not yet included.
            var toAdd = new List <int>(_mstNodes.Count);
            // If the index node is already included.
            var inMst = new bool[_distances.CacheSize];
            // The spanning edges.
            var mstEdges = new List <GraphEdge>(_mstNodes.Count);

            for (var i = 0; i < _mstNodes.Count; i++)
            {
                var index = _mstNodes[i].DistancesIndex;
                if (index != startIndex)
                {
                    toAdd.Add(index);
                    var adjacentEdge = new LinkedGraphEdge(startIndex, index);
                    adjacentEdgeQueue.Enqueue(adjacentEdge, _distances[startIndex, index]);
                }
            }
            inMst[startIndex] = true;

            while (toAdd.Count > 0 && adjacentEdgeQueue.Count > 0)
            {
                int             newIn;
                LinkedGraphEdge shortestEdge;
                // Dequeue and ignore edges that are already inside the MST.
                // Add the first one that is not.
                do
                {
                    shortestEdge = adjacentEdgeQueue.Dequeue();
                    newIn        = shortestEdge.Outside;
                } while (inMst[newIn]);
                mstEdges.Add(new GraphEdge(
                                 _distances.IndexToNode(shortestEdge.Inside),
                                 _distances.IndexToNode(shortestEdge.Outside)));
                inMst[newIn] = true;

                // Find all newly adjacent edges and enqueue them.
                for (var i = 0; i < toAdd.Count; i++)
                {
                    var otherNode = toAdd[i];
                    if (otherNode == newIn)
                    {
                        toAdd.RemoveAt(i--);
                    }
                    else
                    {
                        var edge = new LinkedGraphEdge(newIn, otherNode);
                        adjacentEdgeQueue.Enqueue(edge, _distances[newIn, otherNode]);
                    }
                }
            }

            SpanningEdges = mstEdges;
            IsSpanned     = true;
        }
コード例 #2
0
        public void TestMST()
        {
            // 0 -- 1 -- 2 -- 3
            //  \        |   /
            //    \      | /
            //      4 -- 5 -- 6 -- 7
            bool[,] graph1 = {
                                 { false, true,  false, false, true,  false, false, false },
                                 { true,  false, true,  false, false, false, false, false },
                                 { false, true,  false, true,  false, true,  false, false },
                                 { false, false, true,  false, false, true,  false, false },
                                 { true,  false, false, false, false, true,  false, false },
                                 { false, false, true,  true,  true,  false, true,  false },
                                 { false, false, false, false, false, true,  false, true  },
                                 { false, false, false, false, false, false, true,  false },
                             };

            SearchGraph searchGraph1 = SearchGraphFromData(graph1);

            Dictionary<int, GraphNode> graphNodes1 = GetGraphNodesIdIndex(searchGraph1);

            var mstNodes1 = new List<GraphNode>
                { graphNodes1[3], graphNodes1[5], graphNodes1[7], graphNodes1[0] };
            var distances = new DistanceLookup(mstNodes1);
            var mst1 = new MinimalSpanningTree(mstNodes1.Select(n => n.DistancesIndex).ToList(), distances);
            mst1.Span(graphNodes1[0].DistancesIndex);

            Assert.AreEqual(3, mst1.SpanningEdges.Count, "Wrong amount of spanning edges");
            var goalEdges = new[]
            {
                new []{0, 5}, new []{5, 3}, new []{5, 7}
            };
            foreach (var edge in goalEdges)
            {
                Assert.AreEqual(1,
                    mst1.SpanningEdges.Select(e => new Tuple<ushort, ushort>(distances.IndexToNode(e.Inside).Id, distances.IndexToNode(e.Outside).Id)).Count(
                        t =>
                            (t.Item1 == edge[0] && t.Item2 == edge[1]) ||
                            (t.Item1 == edge[1] && t.Item2 == edge[0])),
                    "Edge " + edge + " not contained exactly once.");
            }
        }