簡體   English   中英

用於對兩個不相交集執行並運算的數據結構

[英]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]將給出代表下一項的整數。 最后,鏈接會環回,因此這些集合必定是不相交的。

令人高興的是,您可以通過交換兩個項目將兩個集合合並在一起。 如果您有索引s1s2 ,那么它們所在的集合( s1s2不是特殊代表,您可以通過任何元素引用集合)可以通過交換這些位置來合並:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM