繁体   English   中英

如何通过链表实现不相交集数据结构?

[英]How to implement a Disjoint-set data structure by Linked list?

我不知道如何通过链表实现不连续集数据结构?谁能告诉我?我特别困惑于find-set()如何在这种实现中工作O(1)时间。thx〜

尽管不相交集数据结构通常被解释为树的森林,但通常使用数组来实现:一个数组将索引映射到其父级索引,而一个数组将索引映射到其父级。 这消除了很多无意义的开销(在空间和时间上),这在理论上是不相关的,但实际上是这样。 您可能需要一种在某种对象的索引和实例之间进行映射的方法。

顺便说一句, find在O(1)中不起作用。 具有等级的技巧可以防止find花费线性时间,但在最坏的情况下,仍然可以采取对数步长。 O(α(n))时间是一个摊销时间,要解释它的来源很棘手-您可以在“好的但不是线性集联合算法[Tarjan]”的效率中找到分析。

这是一种可行的方法:

disjoint_set {
    int[] parent, rank;
    makeset(int n)
    {
        rank = new int[n];
        parent = new int[n];
        for(int i = 0; i < n; i++)
            parent[i] = i;
    }

    int find(int i)
    {
        if (parent[i] != i)
            parent[i] = find(parent[i]);
        return parent[i];
    }

    void union(int x, int y)
    {
        x_root = find(x);
        y_root = find(y);
        if (x_root != y_root) {
            if (rank[x_root] < rank[y_root])
                parent[x_root] = y_root;
            else if (rank[x_root] > rank[y_root])
                parent[y_root] = x_root;
            else {
                parent[y_root] = x_root;
                rank[x_root]++;
            }
        }
    }
}

不相交的集合数据结构在每个操作中都不会在O(1)时间内起作用。 而是在大量操作中以O(1)的时间工作。

每个节点都存储一个指向其父节点的指针,每个不相交集的代表元素是您尽可能跟随父指针的节点。 要到达O(1),必须折叠父节点链,以便每当您跟随父链接时每个元素都指向头节点。

这是完成所有这些操作的一些Python代码。 特别要注意head方法中的第二个while循环:这是使数据结构有效工作的关键。

class Node:
    def __init__(self, value):
        self.value = value
        self.parent = None

    def head(self):
        head = self
        while head.parent:
            head = head.parent
        while self != head:
            self.parent, self = head, self.parent
        return head

    def union(a, b):
        if a.head() != b.head():
            a.head().parent = b.head()


nodes = [Node(i) for i in range(10)]
nodes[0].union(nodes[1])
nodes[0].union(nodes[2])

print set(node.head().value for node in nodes)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM