算法板子记录第一天:并查集(找爸爸)
并查集,处理不相交集的合并和查询的数据结构,俗称:找爸爸
最先写这个数据结构就是他使用的存储结构最简单,一个数组搞定,当然有别的需要可以另加嘛
int num; //节点数量
int fa[num*2]; //存储节点的上级
int rank[num]; //每个节点的高度
初始化父亲数组
void init(){
for(int i=0;i<=num;i++){
fa[i]=[i]; //初始时,每个人的上级都是自己;
rank[i]=1; //每个节点的高度均为1
}
}
查询最高级(祖宗)
int find(int x){
if(x==fa[x]) return x; //找到最高级,输出
else return find(fa[x]);//没找到,递归继续找
}
合并不相交集
void Union(int x,int y){
int fx=find(x); //x的老大
int fy=find(y); //y的老大
//如果x,y不在同一集合
if(fx!=fy){
fa[fx]=fy; //合并x,y所在的集合
}
}
查询时路径压缩,所有人除了老大,上级都是老大
int find_1(int x){
if(x==fa[x]) return x;
else return fa[x]=find_1(fa[x]); //这样查询老大时候自动升级上级为老大
}
合并不相交集,按rank优化
void Union_1(int x,int y){
int fx=find_1(x);
int fy=find_1(y);
if(fx!=fy){
//按rank合并,避免一根线
if(rank[fx]<rank[fy]) fa[fx]=fy;
esle {
fa[fy]=fx;
if(rank[fx]==fa[fy])
rank[fx]++;
}
}
}
本质上,并查集应该是图的一种,合并森林,快速查询,。其复杂度类似于数o(h);不过在此不一定都是只有一棵树,查询一次复杂度应为o(log * n);
log* n 叫做 Iterated logarithm,n<=2^65536时,log*n<=5;
O(log n) 的时间复杂度已经很快了,O(log* n) 是比O(log n) 还要快,近似等于O(1),比O(1)慢一点。!