并查集

所谓并查集,就是将N个不同的元素分成一组不相交的集合

在数据结构中有一种很典型的朋友圈问题,假设有10个人,分别为0到9号,若1和2是朋友,2和3是朋友,3和4是朋友,则成这4个人为一个朋友圈,又有5和6是朋友,7和8是朋友,7和9是朋友,0没有朋友,问这个9个人中有多少朋友圈,这时虽然方法也有,但相对于我们介绍的这种结构,其他的开销就太大了。

结构:

开始时,每个元素就是一个集合,并且初始化为-1,然后按规律将将个集合进行合并。

这里写图片描述
当两个集合合并时,如(1,2)合并,把1作为根,将2所在位置的数值加到1所在位置上,并将2位置数值改为他的根(即1);反过来也可以。
这样操作完成之后,下标为负数的一定为根,且其数值的绝对值为集合中的元素个数,下标为非负数的则是他的根。我们只需要查找有几个负数节点就可以知道有几个集合了;

将我们的例题进行合并后:
这里写图片描述
代码如下:

class UnionFindSet//并查集
{
public:
    UnionFindSet(size_t n)
    {
        _set.resize(n, -1);
    }
    int FindRoot(int x)
    {
        while (_set[x] >= 0)
            x = _set[x];
        return x;
    }
    void Union(int x1, int x2)
    {
        int root1 = FindRoot(x1);
        int root2 = FindRoot(x2);
        if (root1 != root2)
        {
            _set[root1] += _set[root2];
            _set[root2] = root1;
        }
    }
    bool IsIn(int x1, int x2)
    {
        int root1 = FindRoot(x1);
        int root2 = FindRoot(x2);
        if (root1 == root2)
            return true;
        return false;
    }
protected:
    vector<int> _set;
};
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页