/// <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); }
/// <summary> /// Not the paper's version either, since it always propagates the same collision sets. /// </summary> /// <param name="colSets">The collision sets of the _child_ of fromNode</param> /// <param name="fromNode"></param> void RMStarCollisionBackPropagation(DisjointSets <int> colSets, WorldState fromNode) { if (this.debug) { Debug.Print("Back prop!!"); } var queue = new Queue <WorldState>(); queue.Enqueue(fromNode); while (queue.Count != 0) { var node = queue.Dequeue(); bool onlyUnitedNow = node.collisionSets.CopyUnions(colSets); if (onlyUnitedNow) { if (this.debug) { Console.WriteLine("Re-opening node {0} with an updated collision set", node); } this.reinsertIntoOpenList(node); foreach (var next in node.backPropagationSet) { queue.Enqueue(next); } } } }
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 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. } } } }