数据结构——并查集
一、并查集是什么?
有a,b,c,d,e这五个人,分小组,a跟b玩的好,他俩一组,c,d,e没人跟他们玩,他们三每人一组。
问:分了多少组?
结果显而易见,分了4组。
并查集就是要解决这种问题——分了几组?
二、并查集详解
1.设立变量
count
:分的组数int *parent
:关键数组
2.初始化
n是有多少位同学。
UF(int n) {
count = n;//初始化时,每人一组,总共n组
parent = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;//第i位同学跟第i位玩的好(也就是自己跟自己玩的好,谁不爱自己呢?^_^)
}
}
3.传入好朋友
你分组肯定要有个组长,传入两个小可爱,你需要先判断他俩是不是一组的,怎么判断,需要找他俩组长一样不一样(有困难找组长吗 )。
void Union(int p, int q) {
int rootP = Find(p);//找组长
int rootQ = Find(q);//找组长
if (rootP == rootQ)//组长一样,直接返回
return;
parent[rootQ] = rootP;// rootP与rootQ玩的好,他俩分到一组
// 有两个人分到一组了,组数减1
count--;
}
4.找组长
由于你不知道组长是谁,咱们需要挨个人问谁是组长。
组长有特权,就是他跟自己玩的好。
int Find(int x) {
if (parent[x] != x) {
parent[x] = Find(parent[x]);
}
return parent[x];
}
5.分为几个小组啊?
int Count() {
return count;
}
6.同学a跟同学c是一组的吗?
看看他俩组长一样不一样就行了。
bool Connected(int p, int q) {
int rootP = Find(p);
int rootQ = Find(q);
return rootP == rootQ;
}
总结
图片属实不太会,以后我再学学
完整代码:
#include<iostream>
#include<vector>
using namespace std;
class UF {
//private:
public:
// 连通分量个数
int count;
// 存储每个节点的父节点
int* parent;
// n 为图中节点的个数
UF(int n) {
count = n;
parent = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
// 将节点 p 和节点 q 连通
void Union(int p, int q) {
int rootP = Find(p);
int rootQ = Find(q);
if (rootP == rootQ)
return;
parent[rootQ] = rootP;// rootP变成rootQ的儿子
// 两个连通分量合并成一个连通分量
count--;
}
// 判断节点 p 和节点 q 是否连通
bool Connected(int p, int q) {
int rootP = Find(p);
int rootQ = Find(q);
return rootP == rootQ;
}
int Find(int x) {
if (parent[x] != x) {
parent[x] = Find(parent[x]);
}
return parent[x];
}
// 返回图中的连通分量个数
int Count() {
return count;
}
};
void main() {
UF uf(8);
int a[4][2] = { {1,2},{2,7},{3,4},{5,6}};
for (int i = 0; i < 4; i++)
uf.Union(a[i][0], a[i][1]);
int c = uf.Count();
cout <<c << endl;
}