并查集

并查集 union & find
 
是一种树型的数据结构,用于处理一些不交集(Disjoint Sets)的合并及查询问题。一般用数组实现。

Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集。

Union:将两个子集合并成同一个集合。

在现实生活中的例子

1. 小弟 => ⽼大

2. 帮派识别

3. 两种优化⽅方式:小组织和大组织合并时的优化、路径压缩

并查集的初始化,每个元素的root指向自己:

根据合并关系改变元素的root指向,两个集合的合并就是把一个集合的尾部的root指向另一个集合的尾部:

function MakeSet(x)
    x.parent := x

function Find(x)
    if x.parent == x:
        return x
    else:
        return Find(x.parent)

function Union(x, y):
    xRoot := Find(x)
    yRoot := Find(y)
    xRoot.parent := yRoot

  

并查集优化

1. 合并子集时,显然右边并查集的深度(rank)小的情况更好,便于搜索root。把深度较低的子集 merge 到深度较高的子集中去

function Union(x, y):
    xRoot := Find(x)
    yRoot := Find(y)
    if xRoot == yRoot:
        return

    if xRoot.rank < yRoot.rank:
        xRoot.parent := yRoot
    
    else if xRoot.rank > yRoot.rank:
        yRoot.parent := xRoot

    else:
        yRoot.parent := xRoot
        xRoot.rank += 1

 2. 更有效,路径压缩。一般做了这个优化,优化一就可做可不做了。

class QuickUnionUF:
    roots = []
    count = 0

    def __init__(self, n):
        self.count = n
        for i in range(n):
            self.roots.append(i)
    
    def isConnected(self, p, q):
        if self.find(p) == self.find(q):
            return True
        return False
    
    def find(self, p):
        root = p
        while root != self.roots[root]:
            root = self.roots[root]
        # 路径压缩
        while p != self.roots[p]:
            tmp = self.roots[p]
            self.roots[p] = root
            p = tmp
        return root

    def union(self, p, q):
        pRoot = self.find(p)
        qRoot = self.find(q)
        self.roots[pRoot] = qRoot

  

原文地址:https://www.cnblogs.com/chaojunwang-ml/p/11341371.html