1.使用id数组来表示集合
#ifndef UNIONFIND__H
#define UNIONFIND__H
#include <iostream>
#include <cassert>
using namespace std;
class UnionFind{
public:
// 构造函数
UnionFind(int count)
{
id = new int[n];
for(int i = 0; i < count; i++)
{
id[i] = i;
}
this->count= count;
}
~UnionFind()
{
delete[] id;
}
// quick find O(1)
int find(int p)
{
assert(p >= 0 && p < count);
return id[p];
}
// 判断两个元素是否连接
bool isConnected(int p, int q)
{
return id[p] == id[q];
}
// o(n) 将两个元素的集合合并
void unionElements(int p, int q)
{
int pID = find(p);
int qID = find(q);
if(pID == qID)
return ;
for(int i = 0; i < count; i++)
{
if(id[i] == pID)
id[i] == qID;
}
}
private:
int* id;
int count;
};
2.使用树的结构来决定集合
class UnionFind2{
public:
UnionFind2(int count)
{
parent = new int[count];
for(int i = 0; i < count; i++)
parent[i] = i;
this->count = count;
}
~UnionFind2()
{
delete[] parent;
}
int find(int p)
{
assert(p >= 0 && p < count);
while(p != parent[p])
p = parent[p];
return p;
}
bool isConnected(int p, int q)
{
return parent[p] == parent[q];
}
// o(n) 将两个元素的集合合并
void unionElements(int p, int q)
{
int pRoot = find(p);
int qRoot = find(q);
if(pRoot == qRoot)
return ;
parent[pRoot] = qRoot;
}
private:
int* parent;
int count;
};
3.树节点集合元素个数来优化
class UnionFind3{
public:
UnionFind3(int count)
{
parent = new int[count];
sz = new int[count];
for(int i = 0; i < count; i++)
{
parent[i] = i;
sz[i] = 1;
}
this->count = count;
}
~UnionFind3()
{
delete[] parent;
delete[] sz;
}
int find(int p)
{
assert(p >= 0 && p < count);
while(p != parent[p])
p = parent[p];
return p;
}
bool isConnected(int p, int q)
{
return parent[p] == parent[q];
}
void unionElements(int p, int q)
{
int pRoot = find(p);
int qRoot = find(q);
if(pRoot == qRoot)
return ;
//p元素集合个数小于q, 则p连接q
if(sz[pRoot] < sz[qRoot])
{
parent[pRoot] = qRoot;
sz[qRoot] += sz[pRoot];
}
else
{
parent[qRoot] = pRoot;
sz[pRoot] += sz[qRoot];
}
}
private:
int* parent;
int* sz;
int count;
};
4.树结点集合的高度来优化,路径压缩
class UnionFind4{
public:
UnionFind4(int count)
{
parent = new int[count];
rank = new int[count];
for(int i = 0; i < count; i++)
{
parent[i] = i;
rank[i] = 1;
}
this->count = count;
}
~UnionFind4()
{
delete[] parent;
delete[] rank;
}
int find(int p)
{
assert(p >= 0 && p < count);
while(p != parent[p])
p = parent[p];
return p;
}
bool isConnected(int p, int q)
{
return parent[p] == parent[q];
}
void unionElements(int p, int q)
{
int pRoot = find(p);
int qRoot = find(q);
if(pRoot == qRoot)
return ;
if(rank(pRoot) < rank(qRoot))
{
parent[pRoot] = qRoot;
}
else if(rank(pRoot) > rank(qRoot))
{
parent[qRoot] = pRoot;
}
else
{
parent[pRoot] = qRoot;
rank(pRoot) ++;
}
}
private:
int* parent;
int* rank;
int count;
};