c++实现并查集

66 阅读2分钟

并查集(Disjoint-set Union,DSU),也称作不相交集合数据结构,是一种用来管理元素分组的数据结构。它主要支持两种操作:查找(Find)和合并(Union)。查找操作用于确定某个元素属于哪个组,而合并操作则用于将两个组合并成一个。

以下是一个简单的并查集的 C++ 实现:

#include <iostream>
#include <vector>

class UnionFind {
private:
    std::vector<int> parent; // 存储每个节点的父节点
    std::vector<int> rank;   // 存储每个根节点的秩(树的高度)

public:
    // 构造函数:初始化并查集,将每个元素的父节点设为自身,秩设为 0
    UnionFind(int n) : parent(n), rank(n, 0) {
        for (int i = 0; i < n; ++i) {
            parent[i] = i;
        }
    }

    // 查找操作:返回元素 x 所在组的根节点
    int find(int x) {
        if (parent[x] != x) {
            parent[x] = find(parent[x]); // 路径压缩
        }
        return parent[x];
    }

    // 合并操作:将元素 x 所在的组和元素 y 所在的组合并
    void merge(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        if (rootX != rootY) {
            // 将秩较小的根节点连接到秩较大的根节点上
            if (rank[rootX] < rank[rootY]) {
                parent[rootX] = rootY;
            } else if (rank[rootX] > rank[rootY]) {
                parent[rootY] = rootX;
            } else {
                parent[rootY] = rootX;
                rank[rootX]++;
            }
        }
    }

    // 检查两个元素是否属于同一个组
    bool isConnected(int x, int y) {
        return find(x) == find(y);
    }
};

int main() {
    int n = 5;
    UnionFind uf(n);

    // 合并一些组
    uf.merge(0, 1);
    uf.merge(2, 3);
    uf.merge(0, 4);

    // 检查一些元素是否属于同一个组
    std::cout << "Is 1 connected to 4? " << std::boolalpha << uf.isConnected(1, 4) << std::endl;
    std::cout << "Is 2 connected to 3? " << std::boolalpha << uf.isConnected(2, 3) << std::endl;

    return 0;
}

在这个示例中,我们定义了一个 UnionFind 类来实现并查集。它包含了 parentrank 两个私有成员变量,分别用来存储每个元素的父节点和每个根节点的秩。构造函数用来初始化并查集,将每个元素的父节点设为自身,秩设为 0。find() 函数用来查找某个元素所在组的根节点,并进行路径压缩优化。merge() 函数用来将两个组合并,它首先找到两个元素所在组的根节点,然后根据秩的大小合并。isConnected() 函数用来检查两个元素是否属于同一个组。