并查集实现|并查集在相关题目中的应用|手撕数据结构专栏

前言

那么这里博主先安利一下一些干货满满的专栏啦!

高质量干货博客汇总icon-default.png?t=N7T8http://t.csdnimg.cn/jdQXqGit企业开发控制理论和实操icon-default.png?t=N7T8http://t.csdnimg.cn/PyPJeDocker从认识到实践再到底层原理icon-default.png?t=N7T8http://t.csdnimg.cn/G6Inp手撕数据结构icon-default.png?t=N7T8http://t.csdnimg.cn/XeyJn


这里是很多数据结构的模拟实现源码,都是我自己编写的仿照stl风格的数据结构模拟实现。

GitHub - Yufccode/CPlusPlus-review-main: 这是我复习C++的时候所用的一些代码和文件这是我复习C++的时候所用的一些代码和文件. Contribute to Yufccode/CPlusPlus-review-main development by creating an account on GitHub.icon-default.png?t=N7T8https://github.com/Yufccode/CPlusPlus-review-main


并查集

并查集的表示

1. 像堆类似,用下标表示关系

2. 双亲表示法

一开始数组存的是-1,表示每个数都是一棵树,每个数表示一个集合

假设数组:

int a = [-1,-1,-1,-1,-1];

这个数组进行一次合并之后变成:

int a = [-1,0,-1,-1,-1];

这个表示下标为1的数的父亲就是下标为0的数。

如果下标为负数,那么这个数就是树的根。

并查集实现|并查集在相关题目中的应用|手撕数据结构专栏_第1张图片

合并

找根,只能是根的合并。

谁合并谁没有严格的要求(压缩路径才需要要求,一般性能要求比较高才需要压缩路径)。

并查集实现

template 
class union_find_disjoint_set
{
private:
    std::vector __ufs; // 通过编号找人
public:
    union_find_disjoint_set(size_t n)
        : __ufs(n, -1) {} // 先初始化成-1
    void Union(int x1, int x2)
    {
        int root1 = FindRoot(x1);
        int root2 = FindRoot(x2);
        if (root1 == root2) // 如果在一个集合就没必要合并了
            return;
        if (root1 > root2)
            std::swap(root1, root2); // 统一让下标小的根去合并大的根,其实这个是没有要求的
        __ufs[root1] += __ufs[root2];
        __ufs[root2] = root1;
    }
    int FindRoot(int x)
    {
        int root = x;
        while (__ufs[root] >= 0)
            root = __ufs[root];
        return root;
    }
    bool InSet(int x1, int x2) // 判断是否在同一个集合
    {
        return FindRoot(x1) == FindRoot(x2);
    }
    size_t SetSize()
    {
        size_t cnt = 0;
        for (const auto &e : __ufs)
            if (e < 0)
                ++size;
        return size;
    }
};

相关题目

547. 省份数量

https://leetcode.cn/problems/number-of-provinces/description/icon-default.png?t=N7T8https://leetcode.cn/problems/number-of-provinces/description/把并查集复制进去。这样调用即可。

class Solution {
public:
    int findCircleNum(vector>& isConnected) {
        union_find_disjoint_set ufs(isConnected.size());
        for(size_t i = 0; i

990. 等式方程的可满足性

class Solution {
public:
    bool equationsPossible(vector& equations) {
        std::vector ufs(26, -1);
        auto findroot = [&ufs](int x){
            while(ufs[x]>=0)
                x = ufs[x];
            return x;
        };
        // 第一遍,先把相等的值加到一个集合中来
        for(auto& str : equations)
        {
            if(str[1] == '=')
            {
                int root1 = findroot(str[0] - 'a');
                int root2 = findroot(str[3] - 'a');
                if(root1 != root2)
                {
                    ufs[root1] += ufs[root2];
                    ufs[root2] = root1;
                }
            }
        }
        // 第二遍,看看不相等的是否会出现在一个集合中
        for(auto& str : equations)
        {
            if(str[1] == '!')
            {
                int root1 = findroot(str[0] - 'a');
                int root2 = findroot(str[3] - 'a');
                if(root1 == root2)
                {
                    return false;
                }
            }
        }
        return true;
    }
};

你可能感兴趣的:(算法,手撕数据结构,数据结构,图,并查集,C++)