文章目录
并查集
并查集主要解决,对于给定某一集合问题,需要对其进行大量的查询操作,比如说要查找一个点的祖先结点,或者查找两个点是否属于同一个集合,或者是查找连通分量的个数。(肥肠好用
并查集由一个整数型的数组和两个函数构成。
- 数组pre[] 记录了每个点的上级是谁
-== 函数Find() 找到某个点的祖先是谁==
-== 函数Join() 将两个点所在的连通分支合在一起==
嗯…拿朋友圈举例。给定一群人,他们各自有各自的朋友,因为朋友的朋友就是我的朋友嘛,所以各个朋友圈逐渐连通扩大,形成一个部落。两个部落之间划分的很清楚,因为两个部落里面没有人互相认识。这个朋友圈逐渐扩大形成一个部落的过程就采用Join函数。看某个人在不在这个朋友圈里应用的就是Find函数了。
拿代码说话:
Find()函数找祖先:
int Find(int x){ //找根节点,也就是找祖先是谁
int r=x;//委托r去找
while(r!=pre[r]){ //如果r本身不是自己的根节点,也就是自己不是自己的祖先
r=pre[r];//让r的上级去找
}
int i=x,j;
while(pre[i]!=r)//路径压缩
{
j=pre[i];
pre[i]=r;
i=j; //让r的上级,r的上级的上级...以及r都直接作为祖先的直属下级
}
return r;
}
Join()函数连接两个点的连通分支
int Join(int x,int y){ //朋友圈扩大~
int fx=Find(x);
int fy=Find(y);
if(fy!=fx){ //如果他俩的祖先不一样
pre[fy]=fx; //随便把谁作为谁的上级,连接即可~
}
}
以及不要忘记初始化pre数组:
int pre[10005];//存放根节点
int init(){ //初始化pre数组
for(int i=0;i<10005;i++){
pre[i]=i;
}
}
链接一道题 ~ :
L2-024 部落 (并查集与set容器的应用)
关于set容器的基本操作
set作为一个容器也是用来存储同一数据类型的数据类型,并且能从一个数据集合中取出数据,在set中每个元素的值都唯一,不会有重复的元素。而且系统能根据元素的值自动进行排序。应该注意的是set中数元素的值不能直接被改变。
set容器的基本操作:
begin()返回指向第一个元素的迭代器(迭代器和指针用法类似)
count(x)返回x值元素的个数
empty()如果集合为空,返回true
end()返回指向最后一个元素的迭代器
eraser(x)删除集合中的x元素
find(x)返回一个指向被查找元素的迭代器
insert(y)把y插进集合,继续保持顺序
max_size()返回集合能容纳元素的最大限值
size()返回集合中元素的总个数
clear()清空集合中的元素
swap(st2)交换两个集合变量(注意这里是两个集合的变量,st2指的是第二个集合名)
定义:
#include<iostream>
#include<set>
using namespace std;
set<int> s; //容器s里装的是int型的
利用一个迭代器,可以输出set容器里面的数
set<int>::iterator iter;
for(iter = s.begin();iter!=s.end() ;++iter){
cout<<*iter<<" ";
}
关于set容器里元素不重复的验证:
set<int> s;
s.insert(1);
s.insert(3);
s.insert(4);
s.insert(3);
set<int>::iterator iter;
for(iter = s.begin();iter!=s.end() ;++iter){
cout<<*iter<<" ";
}
cout<<endl;
cout<<s.size();
输出结果为
1 3 4
3
关于set容器的练习也可以看上面那个链接,L2-024部落 的那道题解