簡體   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