![](/img/trans.png)
[英]What data structure to use for the implementation of disjoint sets(union find)?
[英]Data structure used to perform the union operation on two disjoint sets
對於兩個不交集的聯合操作,哪種基本數據結構將是最佳選擇?
是否有任何算法可以在O(1)時間內運行?
我在考慮某種形式的哈希表,但是有點卡住了。 這是《算法和數據結構》中的學習指南。
完整的問題:集合操作UNION將兩個不相交的集合S1和S2作為輸入,並返回由S1和S2的所有元素組成的集合S = S1∪S2(集合S1和S2通常被此操作破壞)。 說明如何使用合適的數據結構在O(1)時間內支持UNION操作。 討論您將使用哪種數據結構,並描述UNION操作的算法。
如果集合不相交,則鏈表(帶有頭部和尾部)就足夠了。 在這種情況下,並集只是列表的串聯。 在C ++中:
struct LL {
Value *val;
LL *next;
};
struct LList{
LL *head;
LL *tail;
};
聯合操作將是:
void unify(LList* list1, LList* list2) {
// assuming you take care of edge cases
list1->tail->next = list2->head;
list1->tail = list2->tail;
return;
}
有時適用於該問題的有趣技術(並非總是如此,如您將看到的)是使用“周期”數組,每個周期存儲一個集合。 循環存儲為一堆“下一個元素”鏈接,因此next[i]
將給出代表下一項的整數。 最后,鏈接會環回,因此這些集合必定是不相交的。
令人高興的是,您可以通過交換兩個項目將兩個集合合並在一起。 如果您有索引s1
和s2
,那么它們所在的集合( s1
和s2
不是特殊代表,您可以通過任何元素引用集合)可以通過交換這些位置來合並:
int temp = next[s1];
next[s1] = next[s2];
next[s2] = temp;
或者,您也可以交換語言。 據我所知std::swap(&next[s1], &next[s2])
Java沒有很好的等效於std::swap(&next[s1], &next[s2])
。
這顯然與循環鏈表有關,但更為緊湊。 缺點是您必須事先准備好“宇宙”。 使用鏈接列表,您可以任意添加項目。 同樣,如果您的項不是0到n的整數,則將在側面進行映射,但這並不是真正的不利因素,它取決於您需要使用的方式。
還有一個好處是,因為您可以按索引引用一個項目,所以它與其他數據結構更容易組合在一起,例如,它喜歡與Union Find結構(也是整數數組,其中有兩個整數)合作,繼承兩個結構都提供的O(1)聯合,保留聯合查找的攤銷O(α(n))Find,以及(從循環結構中)保留大小為m的集合的O(m)集枚舉。 因此,您大多數情況下都可以兼得。
如果不太明顯,可以使用“所有單例”初始化“ Universe”,如下所示:
for (int i = 0; i < next.length; i++)
next[i] = i;
與“聯合查找”中的相同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.