根据规模改进联合

在我们当前的 merge 实现中,我们总是选择左侧集合作为正确集合的子集,而不考虑集合的大小。没有这个限制,从元素到其代表的路径(没有路径压缩 )可能很长,从而导致 find 调用的大运行时间。

另一个常见的改进是通过大小启发式联合,它正如它所说的那样:当合并两个集合时,我们总是将较大的集合设置为较小集合的父集合,从而导致最多 StackOverflow 文档 步骤的路径长度 :

我们在我们的类中存储了一个额外的成员 std::vector<size_t> size,它被初始化为每个元素的 1。合并两个集合时,较大的集合成为较小集合的父集合,我们总结了两个大小:

private:
    ...
    std::vector<size_t> size;

public:
    union_find(size_t n) : parent(n), size(n, 1) { ... }

    ...

    void merge(size_t i, size_t j) {
        size_t pi = find(i);
        size_t pj = find(j);
        if (pi == pj) {            // If the elements are in the same set: 
            return;                // do nothing
        }
        if (size[pi] > size[pj]) { // Swap representatives such that pj
            std::swap(pi, pj);     // represents the larger set
        }
        parent[pi] = pj;           // attach the smaller set to the larger one
        size[pj] += size[pi];      // update the size of the larger set
    }