/// <summary> /// Modifies this data structure to also contains all unions from other. /// </summary> /// <param name="other"></param> /// <returns>Whether this object was changed</returns> public bool CopyUnions(DisjointSets <T> other) { // Create a temporary reverse mapping of other's items to its entries - O(n) var otherItemsToEntries = new Dictionary <DisjointSetItem, T>(); foreach (var kvp in other.entriesToItems) { otherItemsToEntries[kvp.Value] = kvp.Key; } // Unite each of other's entries with its representative only - O(n) bool ret = false; foreach (var entryAndSetItem in other.entriesToItems) { var entry = entryAndSetItem.Key; var item = entryAndSetItem.Value; if (item.IsSingle() == true) { continue; } other.Find(item); var repEntry = otherItemsToEntries[item.parent]; bool wasOnlyUnitedNow = this.Union(entry, repEntry); ret = ret || wasOnlyUnitedNow; } return(ret); }
public DisjointSets(DisjointSets <T> other) { entriesToItems = new Dictionary <T, DisjointSetItem>(); maxRank = other.maxRank; var queue = new Queue <T>(other.entriesToItems.Keys); var otherRepsToNewReps = new Dictionary <DisjointSetItem, DisjointSetItem>(); while (queue.Count != 0) { var entry = queue.Dequeue(); var item = other.entriesToItems[entry]; other.Find(item); // Makes item.parent point directly do the set's representative if (item.parent == item) // This is the set's representative { var newItem = new DisjointSetItem(); entriesToItems[entry] = newItem; // .parent already points to itself as needed newItem.rank = item.rank; // Since all items in a set do not point directly to the set's rep, // the set's rank would have been 1 regardless of its size, had it // been created by calls to Union. We prefer to remember the original rank. otherRepsToNewReps[item] = newItem; } else { if (otherRepsToNewReps.ContainsKey(item.parent)) // We've copied this rep already { var newItem = new DisjointSetItem(); entriesToItems[entry] = newItem; newItem.parent = otherRepsToNewReps[item.parent]; // .rank not important in non-rep items } else { queue.Enqueue(entry); // Wait for the rep to be copied first. } } } }