轉載:一個python並查集類

lt發表於2020-02-12

來源:https://www.cnblogs.com/yscl/p/10185293.html

class UnionFind(object):
    """並查集類"""
    def __init__(self, n):
        """長度為n的並查集"""
        self.uf = [-1 for i in range(n + 1)]    # 列表0位置空出
        self.sets_count = n                     # 判斷並查集裡共有幾個集合, 初始化預設互相獨立
    # def find(self, p):
    #     """查詢p的根結點(祖先)"""
    #     r = p                                   # 初始p
    #     while self.uf[p] > 0:
    #         p = self.uf[p]
    #     while r != p:                           # 路徑壓縮, 把搜尋下來的結點祖先全指向根結點
    #         self.uf[r], r = p, self.uf[r]
    #     return p
    # def find(self, p):
    #     while self.uf[p] >= 0:
    #         p = self.uf[p]
    #     return p
    def find(self, p):
        """尾遞迴"""
        if self.uf[p] < 0:
            return p
        self.uf[p] = self.find(self.uf[p])
        return self.uf[p]
    def union(self, p, q):
        """連通p,q 讓q指向p"""
        proot = self.find(p)
        qroot = self.find(q)
        if proot == qroot:
            return
        elif self.uf[proot] > self.uf[qroot]:   # 負數比較, 左邊規模更小
            self.uf[qroot] += self.uf[proot]
            self.uf[proot] = qroot
        else:
            self.uf[proot] += self.uf[qroot]  # 規模相加
            self.uf[qroot] = proot
        self.sets_count -= 1                    # 連通後集合總數減一
    def is_connected(self, p, q):
        """判斷pq是否已經連通"""
        return self.find(p) == self.find(q)     # 即判斷兩個結點是否是屬於同一個祖先

用法例子

>>> uf=UnionFind(5)
>>> uf.uf
[-1, -1, -1, -1, -1, -1]
>>> uf.find(1)
1
>>> uf.find(8)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 21, in find
IndexError: list index out of range
>>> uf.union(1,2)
>>> uf.is_connected(1,2)
True
>>> uf.is_connected(1,3)
False
>>> uf.sets_count
4
>>> uf.union(5,3)
>>> uf.is_connected(1,5)
False
>>> uf.sets_count
3

相關文章