/// <summary>
        ///     Uses Prim's algorithm to build an MST spanning the mstNodes.
        ///     O(|mstNodes|^2) runtime.
        /// </summary>
        /// <param name="startIndex">The node index to start from.</param>
        public void Span(int startIndex)
        {
            // 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 <DirectedGraphEdge>(_mstNodes.Count);

            using (var adjacentEdgeQueue = new LinkedListPriorityQueue <DirectedGraphEdge>(100, _mstNodes.Count * _mstNodes.Count))
            {
                foreach (var t in _mstNodes)
                {
                    if (t != startIndex)
                    {
                        toAdd.Add(t);
                        adjacentEdgeQueue.Enqueue(new DirectedGraphEdge(startIndex, t),
                                                  _distances[startIndex, t]);
                    }
                }
                inMst[startIndex] = true;

                while (toAdd.Count > 0 && !adjacentEdgeQueue.IsEmpty)
                {
                    int newIn;
                    DirectedGraphEdge 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(shortestEdge);
                    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
                        {
                            adjacentEdgeQueue.Enqueue(new DirectedGraphEdge(newIn, otherNode),
                                                      _distances[newIn, otherNode]);
                        }
                    }
                }
            }

            SpanningEdges = mstEdges;
        }
 private void InitializeDataStructures(
     int startIndex, int[] notIncluded, ref int notIncludedCount,
     LinkedListPriorityQueue <DirectedGraphEdge> adjacentEdgeQueue)
 {
     for (var i = 0; i < _mstNodes.Count; i++)
     {
         var t = _mstNodes[i];
         if (t != startIndex)
         {
             notIncluded[notIncludedCount] = t;
             notIncludedCount++;
             var distance = _distances[startIndex, t];
             adjacentEdgeQueue.Enqueue(new DirectedGraphEdge(startIndex, t), distance);
         }
     }
 }
        public void Test()
        {
            int[] queueTestOrder = { 10, 3, 11, 6, -3, 17, 13, -6, 2, 8, -2, -8 };

            var queue = new LinkedListPriorityQueue <TestNode>(30, queueTestOrder.Length);

            foreach (int t in queueTestOrder)
            {
                if (t > 0)
                {
                    queue.Enqueue(new TestNode(t), (uint)t);
                }
                if (t < 0)
                {
                    Assert.IsTrue(queue.Dequeue().Priority == -t);
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        ///     Uses Prim's algorithm to build an MST spanning the mstNodes.
        ///     O(|mstNodes|^2) runtime.
        /// </summary>
        /// <param name="startIndex">The node index to start from.</param>
        public IReadOnlyList <DirectedGraphEdge> Span(int startIndex)
        {
            var notIncluded = ArrayPool <int> .Shared.Rent(_mstNodes.Count);

            var notIncludedCount = 0;

            var isIncluded = ArrayPool <bool> .Shared.Rent(_distances.CacheSize);

            Array.Clear(isIncluded, 0, isIncluded.Length);

            _spanningEdges?.Dispose();
            _spanningEdges = new PooledList <DirectedGraphEdge>(_mstNodes.Count);

            using (var adjacentEdgeQueue = new LinkedListPriorityQueue <DirectedGraphEdge>(100, _mstNodes.Count * _mstNodes.Count))
            {
                InitializeDataStructures(startIndex, notIncluded, ref notIncludedCount, adjacentEdgeQueue);
                isIncluded[startIndex] = true;

                while (notIncludedCount > 0 && !adjacentEdgeQueue.IsEmpty)
                {
                    int newIn;
                    DirectedGraphEdge 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 (isIncluded[newIn]);

                    _spanningEdges.Add(shortestEdge);
                    isIncluded[newIn] = true;

                    // Find all newly adjacent edges and enqueue them.
                    IncludeNode(notIncluded, ref notIncludedCount, adjacentEdgeQueue, newIn);
                }
            }

            ArrayPool <bool> .Shared.Return(isIncluded);

            ArrayPool <int> .Shared.Return(notIncluded);

            return(_spanningEdges);
        }
 private void IncludeNode(
     int[] notIncluded, ref int notIncludedCount,
     LinkedListPriorityQueue <DirectedGraphEdge> adjacentEdgeQueue,
     int node)
 {
     for (var i = 0; i < notIncludedCount; i++)
     {
         var otherNode = notIncluded[i];
         if (otherNode == node)
         {
             RemoveAt(notIncluded, ref notIncludedCount, i);
             i--;
         }
         else
         {
             var distance = _distances[node, otherNode];
             adjacentEdgeQueue.Enqueue(new DirectedGraphEdge(node, otherNode), distance);
         }
     }
 }