按等级改进联合

另一种通常使用的启发式方法,而不是按大小联合,是按级别启发式联合

它的基本思想是我们实际上并不需要存储集合的确切大小,大小的近似值(在这种情况下:大致是集合大小的对数)足以达到与大小相同的速度。

为此,我们引入了集合等级的概念,其给出如下:

  • 单例排名 0
  • 如果合并了具有不等等级的两个集合,则具有较大等级的集合变为父集合而等级保持不变。
  • 如果合并了两组相等的等级,则其中一组成为另一组的父级(选择可以是任意的),其等级递增。

按等级联合的一个优点是空间使用:随着最大等级大致增加 StackOverflow 文档 ,对于所有实际输入大小,等级可以存储在单个字节中(因为 n < 2^255)。

按等级简单实现并集可能如下所示:

private:
    ...
    std::vector<unsigned char> rank;

public:
    union_find(size_t n) : parent(n), rank(n, 0) { ... }

    ...

    void merge(size_t i, size_t j) {
        size_t pi = find(i);
        size_t pj = find(j);
        if (pi == pj) {
            return;
        }
        if (rank[pi] < rank[pj]) {
            // link the smaller group to the larger one
            parent[pi] = pj;
        } else if (rank[pi] > rank[pj]) {
            // link the smaller group to the larger one
            parent[pj] = pi;
        } else {
            // equal rank: link arbitrarily and increase rank
            parent[pj] = pi;
            ++rank[pi];
        }
    }