接口的主要內容如下:
1、並查集初始化
2、合併:合併兩棵樹
3、查找:找某一節點所在樹的根節點
4、連通性判斷:判斷兩個節點是否連通,實質是判斷其根節點是否相同
5、路徑壓縮:降低樹的高度,進而降低查找的複雜度
6、連通分量個數統計
7、平衡性:使用size統計每棵樹的節點數量,在合併的時候,總是讓重量較小的樹合併到重量較大的樹的下方(即小樹的根節點指向大樹的根節點),避免樹的高度變得不平衡。
#include <vector>
using namespace std;
// 並查集
class UnionFind
{
private:
int count; // 並查集中連通分量的個數
vector<int> size; // 存儲樹的"重量",用於在兩顆樹合併時,平衡樹的高度
vector<int> parent; // 存儲節點
public:
// 並查集初始化,開始時每個節點都是獨立的
UnionFind(int n)
{
this->count = n;
parent.resize(n);
size.resize(n);
for (int i = 0; i < n; ++i)
{
parent[i] = i;
size[i] = 1;
}
}
// 返回當前集合中連通分量的個數
int count()
{
return this->count;
}
// 查找某個連通分量的根節點
int findRoot(int x)
{
while (parent[x] != x)
{
parent[x] = parent[parent[x]]; // 路徑壓縮
x = parent[x];
}
return x;
}
// 判斷兩個分量是否連通
bool connected(int p, int q)
{
int root_p = findRoot(p);
int root_q = findRoot(q);
return root_p == root_q;
}
// 合併兩個集合
void UnionSet(int p, int q)
{
int root_p = findRoot(p);
int root_q = findRoot(q);
if (root_p == root_q) return;
if (size[root_p] > size[root_q])
{
parent[root_q] = root_p;
size[root_p] += size[root_q];
}
else
{
parent[root_p] = root_q;
size[root_q] += size[root_p];
}
this->count--;
}
};
謝謝閱讀。