介绍:
并查集数据结构,也称为不相交集合数据结构,是计算机科学中一种强大的工具,可以高效地追踪和合并不相交的集合。在本博客文章中,我们将深入了解UnionFind类的实现细节,并探讨其应用。
代码实现
#include <iostream>
#include <vector>
#include <algorithm>
#include<set>
#include<string>
#include<unordered_set>
#include<unordered_map>
#include<stack>
using namespace std;
class UnionFind
{
private:
int count=0;
vector<int>parent,rank;//rank记录高度
public:
UnionFind( );
UnionFind(int n );
~UnionFind();
int find(int p){
//递归写法
// return (parent[p]==p)?p:(parent[p]=find(parent[p]));
//循环写法
while ( p!=parent[p])
{
p=parent[p];
}
return p;
};
bool isConnected(int p,int q){
return find(p)==find(q);
};
bool unionElements(int p,int q){
int rootP=find(p);
int rootQ=find(q);
if(rootP==rootQ) return false;
if(rank[rootP]<rank[rootQ]){
parent[rootP]=rootQ;
}else if(rank[rootP]>rank[rootQ]){
parent[rootQ]=rootP;
}else{
parent[rootQ]=rootP;
rank[rootP]++;
}
count--;
return true;
};
int getCount(){
return count;
};
};
UnionFind::UnionFind(int n)
{
count=0;
parent.clear();
parent.resize(n);
for(int i=0;i<n;i++){
parent[i]=i;
rank.push_back(1);
}
count=n;
}
UnionFind::~UnionFind()
{
}
代码解析:
UnionFind类是一个并查集的实现。在构造函数UnionFind(int n)中,我们初始化了count变量为0,清空了parent和rank向量,并为parent向量分配了大小为n的空间。然后,通过循环将每个元素的父节点初始化为自身,并将rank向量的每个元素初始化为1。这个构造函数的目的是创建一个具有n个独立集合的并查集。
接下来,我们来看一下UnionFind类的成员函数。find(int p)函数用于查找元素p所属的集合的根节点。它使用了路径压缩的技巧,通过不断向上寻找父节点,将p的父节点更新为根节点,以减少后续查找的时间复杂度。
isConnected(int p, int q)函数用于检查元素p和元素q是否属于同一个集合。它通过调用find函数比较它们的根节点是否相同来判断。
unionElements(int p, int q)函数用于将元素p所属的集合和元素q所属的集合进行合并。它首先找到p和q的根节点,然后根据rank的大小,决定将哪个根节点作为合并后的根节点。如果两个元素的根节点已经相同,表示它们已经属于同一个集合,合并操作不执行。合并操作完成后,更新count变量的值。
getCount()函数用于获取并查集当前包含的集合数量。
应用和扩展:
并查集在许多算法和数据结构中都有广泛的应用。以下是一些常见的应用场景:
1. 连通性问题:可以快速判断两个元素是否连通,如判断图中的两个节点是否属于同一个连通分量。
2. 最小生成树算法:如Kruskal算法和Prim算法,都可以利用并查集来实现。
3. 图像分割:将图像中的像素点划分为不同的区域,可以利用并查集来维护区域的连通性。
4. 社交网络分析:可以利用并查集来判断社交网络中的用户是否属于同一个社区。
结论:
并查集是一种强大且常用的数据结构,用于解决集合和连通性问题, 在力扣中, 岛屿这类划分集合的题,除了广搜,深搜, 也可以考虑用并查集AC