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); }
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); }
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); }
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; } } }