并差集

并差集,顾名思义是关于集合的查找与合并的操作

常用的实现方法有数组,链表,树这三种,虽然方法不同,但是大概思想应该是相同的

我们在什么时候使用并差集

个人认为并差集的使用应该是在题目要求关系点很多并且判断两点或多点是否有某种关系时

例如杭电的     畅通工程    就是给你几行数据,每行数据有两个整数a,b表示a,b之间有路,然后最后一行给你两个点让你判断这两点是否连通

如果用一般的方法就是把路都存下来然后使用图把所有连通点记录,看两点是否连通时间复杂度O(n^2)

并差集的算法则是将所有相连的点看作一个集合,记录完成后查询两点是否在同一集合即可

操作的实现就是首先每个点的上级是他本身然后将连通的两点其中一个作为根节点即可然后继续向下进行直到数据全部记录最后判断两点是否在同一集合即可


当然判断两点是否在同一集合首先要找到这两点各自的根节点再判断根节点是否相同即可

int find(int x)   //寻找根节点              
{
    int r=x;                   
    while (pre[r]!=r)   //找到的上级不是根节点                   
    r=pre[r] ;        //继续向上找    
    return r ;    //找到根节点
}

两点连通,意味着两点所在集合是一个集合

void join(int x,int y)  
{  
    int fx=find(x),fy=find(y);    //找这两个点的根节点  
    if(fx!=fy)             //判断根节点是否相同            
    pre[fx]=fy;             //不同就将两点所在集合合并,操作起来就是将其中一个根节点连到另一个上  
}
还有一个路径压缩


int find(int x)                                                                                                         //查找根节点  
{   
    int r=x;  
    while ( pre[r ] != r )                                                                                              //返回根节点 r  
          r=pre[r ];  
   
    int i=x , j ;  
    while( i != r )    //将根节点变成自己的直属上级                                                                                                    //路径压缩  
    {  
         j = pre[ i ]; // 在改变上级之前用临时变量  j 记录下他的值   
         pre[ i ]= r ; //把上级改为根节点  
         i=j;  
    }  
    return r ;  
}



在C++中,可以用类来实现集合的交并差集。下面是一个示例代码: ```cpp #include <iostream> #include <set> using namespace std; class Set { private: set<int> s; public: Set() {} Set(set<int> s) : s(s) {} Set operator+(Set &rhs) { set<int> res; set_union(s.begin(), s.end(), rhs.s.begin(), rhs.s.end(), inserter(res, res.begin())); return Set(res); } Set operator-(Set &rhs) { set<int> res; set_difference(s.begin(), s.end(), rhs.s.begin(), rhs.s.end(), inserter(res, res.begin())); return Set(res); } Set operator*(Set &rhs) { set<int> res; set_intersection(s.begin(), s.end(), rhs.s.begin(), rhs.s.end(), inserter(res, res.begin())); return Set(res); } void print() { for (auto x : s) { cout << x << " "; } cout << endl; } }; int main() { set<int> s1 = {1, 2, 3}; set<int> s2 = {2, 3, 4}; Set a(s1), b(s2); cout << "集合a:"; a.print(); cout << "集合b:"; b.print(); cout << "集合a与集合b的并:"; Set c = a + b; c.print(); cout << "集合a与集合b的交:"; Set d = a * b; d.print(); cout << "集合a与集合b的差:"; Set e = a - b; e.print(); return 0; } ``` 上面的代码中,我们定义了一个`Set`类,并实现了交、并、差集的操作。`operator+`函数实现了并集,`operator-`函数实现了差集,`operator*`函数实现了交集。然后,我们在`main`函数中创建两个集合`s1`和`s2`,分别初始化为{1,2,3}和{2,3,4},然后将它们转换为`Set`类型的对象`a`和`b`,最后分别调用`+`、`-`、`*`函数,输出结果即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值