用于对两个不相交的集

时间:2015-11-02 20:29:06

标签: java algorithm data-structures union

哪种基本数据结构最适合用于两个不相交集合上的并集操作?

是否有任何算法可以在O(1)时间内运行?

我在想各种各样的哈希表,但我有点卡住了。 这是针对算法和数据结构的学习指南。

完整的问题: 设置操作UNION将两个不相交的集合S1和S2作为输入,并返回a 设置S =S1∪S2由S1和S2的所有元素组成(集合S1和S2为 通常被这次行动摧毁)。解释如何支持UNION操作 在O(1)时间内使用合适的数据结构。讨论你想要的数据结构 使用并描述UNION操作的算法。

2 个答案:

答案 0 :(得分:1)

如果这些集合是不相交的,那么链表(带有头部和尾部)就足够了。在这种情况下,联合只是列表的串联。在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;
}

答案 1 :(得分:0)

有时适用于该问题的有趣技术(并不总是如你所见),是使用“循环”数组,每个循环存储一个集合。循环存储为一堆“下一个元素”链接,因此next[i]将给出一个表示下一个项目的整数。最后,链接循环回来,所以这些集合必然是不相交的。

有一件好事,你可以通过交换两个项目将两个集合在一起。如果您有索引s1s2,那么他们所在的集合(s1s2不是特殊代表,您可以通过其任何元素引用集合)可以通过交换这些职位来联合:

int temp = next[s1];
next[s1] = next[s2];
next[s2] = temp;

或者你可以用你的语言交换。据我所知,Java没有相当于std::swap(&next[s1], &next[s2])的等价物。

这显然与循环链表相关,但更紧凑。缺点是你必须提前准备好你的“宇宙”。使用链接列表,您可以随意添加项目。此外,如果您的项目不是整数0到n,那么您将在侧面有一个数组来进行映射,但这不是一个纯粹的缺点或好处,它取决于您需要用它做什么。

奖励的好处在于,因为你可以通过索引引用一个项目,它可以更容易地与其他数据结构结合在一起,例如它喜欢与Union Find结构(也是一个整数数组,两个数组)合作其中,继承了两个结构提供的O(1)联盟,保持摊销的O(α(n))联合查找的查找,并且(从循环结构)保持一组的O(m)集枚举大小为m。所以你们大多数都是两全其美的。

如果不明显,你可以像这样用“所有单身人士”初始化“宇宙”:

for (int i = 0; i < next.length; i++)
    next[i] = i;

与Union Find相同。