public void Basic()
        {
            var set = new DisjointSet <int>();

            set.Clear();
            foreach (int v in Enumerable.Range(1, 9))
            {
                set.Add(v);
            }
            foreach (int x in Enumerable.Range(1, 9))
            {
                foreach (int y in Enumerable.Range(1, 9))
                {
                    Assert.IsFalse(x != y && set.IsUnited(x, y));
                }
            }
            set.Unite(1, 9);
            Assert.AreEqual(set.Count, 8);
            Assert.IsTrue(set.IsUnited(1, 9));
            set.Unite(2, 7);
            Assert.AreEqual(set.Count, 7);
            Assert.AreEqual(set.ElementCount, 9);
            set.Unite(7, 1);
            Assert.IsTrue(set.IsUnited(2, 9));
            Assert.IsFalse(set.IsUnited(2, 6));

            Assert.AreEqual(set.Count, 6);
            Assert.AreEqual(set.ElementCount, 9);
        }
Пример #2
0
    public ICollection <IGraphEdge <T> > MinimumSpanningTree(IGraph <T> graph)
    {
        DisjointSet <IGraphNode <T> > nodes = new DisjointSet <IGraphNode <T> >();

        foreach (IGraphNode <T> node in graph.Nodes)
        {
            nodes.Add(node);
        }

        PriorityQueue <QueueType> edges = new PriorityQueue <QueueType>(graph.EdgeCount);

        foreach (IGraphEdge <T> edge in graph.Edges)
        {
            edges.Add(new QueueType(edge.weight, edge));
        }

        List <IGraphEdge <T> > ret = new List <IGraphEdge <T> >(graph.NodeCount);

        while (edges.Count > 0)
        {
            IGraphEdge <T> edge = edges.Pop().Second;
            if (nodes.AreUnited(edge.node1, edge.node2))
            {
                continue;
            }
            ret.Add(edge);
            nodes.Union(edge.node1, edge.node2);
        }

        return(ret);
    }
        public int CountComponents(int numNodes, int[,] edges)
        {
            DisjointSet set = new DisjointSet();

            for (int i = 0; i < edges.GetLength(0); i++)
            {
                set.Add(edges[i, 0]);
                set.Add(edges[i, 1]);

                if (set.Union(edges[i, 0], edges[i, 1]))
                {
                    numNodes--;
                }
            }

            return(numNodes);
        }
Пример #4
0
            public void Nack(DisjointSet missingSequences)
            {
                // Add the set of missing sequence numbers to our "reference" set.
                DisjointSet.Add(ref this.Stable, missingSequences);

                // Immediately enqueue these sequence numbers to be sent as part of the next NACK
                // (if we don't receive any other NACK containing them from another client first).
                DisjointSet.Add(ref this.Current, missingSequences);

                this.Debugger("Nacked", missingSequences);
            }
Пример #5
0
        internal static Dictionary <int, List <EDGE> > Search <VERTEX, EDGE>(AdjacencyGraph <VERTEX, EDGE> graph, IComparer <EDGE> comparer)
            where EDGE : class, IAdjacencyEdge, new()
        {
            DisjointSet set = new DisjointSet(graph.VertexCount);

            for (int i = 0; i < graph.VertexCount; i++)
            {
                set.Add(i, i);
            }

            List <EDGE> sorted = graph.GetAllEdges();

            sorted.Sort(comparer);

            int         edgeCount = sorted.Count;
            List <EDGE> edges     = new List <EDGE>(edgeCount);

            for (int i = 0; i < edgeCount; i++)
            {
                int u = sorted[i].From;
                int v = sorted[i].To;

                if (set.Union(v, u))
                {
                    edges.Add(sorted[i]);
                }
            }

            Dictionary <int, List <EDGE> > forest = new Dictionary <int, List <EDGE> >();

            edgeCount = edges.Count;
            for (int i = 0; i < edgeCount; i++)
            {
                int root = set.FindParent(edges[i].From);

                if (!forest.ContainsKey(root))
                {
                    forest.Add(root, new List <EDGE>());
                }

                forest[root].Add(edges[i]);
            }

            return(forest);
        }
        public IEnumerable <object> Assemble(Chunk chunk)
        {
            // Keep track of chunks we have already received.
            // If this is a duplicate chunk return nothing.
            // Note: FrameSequence==0 for real-time ink
            if (chunk.FrameSequence > 0)
            {
                if (DisjointSet.Contains(ref this.m_ReceivedFrameSequences, chunk.FrameSequence))
                {
                    yield break;
                }
                DisjointSet.Add(ref this.m_ReceivedFrameSequences, chunk.FrameSequence);

                // Save space in the ReceivedSequenceNumbers queue by adding all chunks
                // that we can't expect to receive anymore.
                if (chunk.OldestRecoverableFrame > ulong.MinValue)
                {
                    DisjointSet.Add(ref this.m_ReceivedFrameSequences, new Range(ulong.MinValue, chunk.OldestRecoverableFrame - 1));
                }

                // Check the frame sequence number to see if any frames were skipped.
                // If so, then it is likely that the frame has been dropped, so it is
                // necessary to send a NACK.
                if (chunk.FrameSequence > this.m_GreatestFrameSequence + 1ul)
                {
                    Debug.WriteLine(string.Format("*** Frames #{0}-{1} were dropped ({2} total)! Requesting replacements (oldest recoverable is #{3})...",
                                                  this.m_GreatestFrameSequence + 1ul, chunk.FrameSequence - 1ul, chunk.FrameSequence - this.m_GreatestFrameSequence - 1,
                                                  chunk.OldestRecoverableFrame), this.GetType().ToString());
                    //In the CP3 code here we would send the NACK.
                }

                // Assuming the chunk has not been duplicated or received out of order,
                // update our variable containing the highest sequence number seen
                // so far so we know which future frames have been dropped.
                if (chunk.FrameSequence > this.m_GreatestFrameSequence)
                {
                    this.m_GreatestFrameSequence = chunk.FrameSequence;
                }
            }

            // Process single-chunk messages immediately.
            if (chunk.NumberOfChunksInMessage <= 1)
            {
                // Don't create a MessageAssembler for singleton chunks.
                // Instead, just return the message immediately.
                using (MemoryStream ms = new MemoryStream(chunk.Data)) {
                    yield return(this.m_Formatter.Deserialize(ms));

                    yield break;
                }
            }

            // For multi-chunk messages, we first attempt to find an existing MessageAssembler
            // instance for the message to which the chunk belongs (based on the range of chunk
            // sequence numbers the message spans).
            MessageAssembler assembler = this.NewestMessageAssember, previous = null;
            object           message;

            for (; ;)
            {
                bool done, remove, complete;

                // If there does not exist any assembler for which IsInRange(chunk) returned true,
                // create one to hold the chunk.
                if (assembler == null)
                {
                    Debug.WriteLine(string.Format("Creating a new MessageAssembler to manage multipart message (message #{0}, chunks #{1}-{2})",
                                                  chunk.MessageSequence,
                                                  chunk.ChunkSequenceInMessage + 1,
                                                  chunk.NumberOfChunksInMessage),
                                    this.GetType().ToString());

                    assembler = new MessageAssembler(chunk.MessageSequence,
                                                     chunk.NumberOfChunksInMessage, this.m_Formatter);

                    // Insert the assembler as the first entry in our linked list,
                    // since it is most likely to be used by subsequent chunks.
                    assembler.NextOldestAssembler = this.NewestMessageAssember;
                    this.NewestMessageAssember    = assembler;
                }

                // See if the chunk belongs to the current assembler.
                if (assembler.MessageSequence == chunk.MessageSequence)
                {
                    // If so, add the chunk to it, and we can stop searching.
                    assembler.Add(chunk);
                    done = true;

                    // If the message has been fully assembled, process it
                    // and remove the no-longer-needed assembler.
                    complete = assembler.IsComplete;
                    if (complete)
                    {
                        message = assembler.DeserializeMessage();
                        remove  = true;
                    }
                    else
                    {
                        message = null;
                        remove  = false;
                    }
                }

                else if (assembler.MessageSequence < chunk.OldestRecoverableMessage)
                {
                    // For each message assembler that is waiting for more chunks (and to which the current
                    // chunk does not belong), make sure it will be possible to complete the message in
                    // the future.  If the sender reports that its OldestRecoverableFrame is greater than
                    // the sequence number of any frame yet needed to complete the message, then no
                    // NACK we send can ever satisfy our needs, so we discard the message completely
                    // (removing the assembler from the linked list).
                    Debug.WriteLine(string.Format("### Giving up on message #{0} (chunks #{0}-{1}): the oldest available chunk is {2}!",
                                                  chunk.MessageSequence,
                                                  chunk.ChunkSequenceInMessage + 1,
                                                  chunk.NumberOfChunksInMessage,
                                                  chunk.OldestRecoverableMessage), this.GetType().ToString());
                    remove   = true;
                    message  = null;
                    done     = false;
                    complete = false;
                }
                else
                {
                    remove   = false;
                    message  = null;
                    done     = false;
                    complete = false;
                }

                // If the assembler is no longer useful, remove it from the linked list.
                // (There are a couple of conditions, above, under which this might happen.)
                if (remove)
                {
                    if (previous == null)
                    {
                        this.NewestMessageAssember = assembler.NextOldestAssembler;
                    }
                    else
                    {
                        previous.NextOldestAssembler = assembler.NextOldestAssembler;
                    }
                }

                // If an assembler was found which accepted the chunk, we're done.
                // (There are a couple of conditions, above, under which this might happen.)
                if (done)
                {
                    if (complete)
                    {
                        yield return(message);
                    }
                    yield break;
                }
                else
                {
                    // Get the next assembler.  Do not break from the loop if there
                    // is no "next" assembler, since one will be created.
                    previous  = assembler;
                    assembler = assembler.NextOldestAssembler;
                }
            }
        }