并查集
它最重要的作用就是用来:检查一个图是否存在环。

#define VERTICES 6
void Init(int parent[], int rank[])
{
for (int i = 0; i < VERTICES; ++i) {
parent[i] = -1;
rank[i] = 0; // 代表当前树高
}
}
int FindRoot(int x, int parent[])
{
int x_root = x;
while (parent[x_root] != -1) {
x_root = parent[x_root];
}
return x_root;
}
int Union(int x, int y, int parent[], int rank[])
{
int x_root = FindRoot(x, parent);
int y_root = FindRoot(y, parent);
if(x_root == y_root) {
return 0;
}
else {
// parent[x_root] = y_root;
if ( rank[x_root] > rank[y_root] ) {
parent[y_root] = x_root;
}
else if ( rank[x_root] < rank[y_root] ) {
parent[x_root] = y_root;
}
else {
parent[x_root] = y_root;
++rank;
}
return 1;
}
}
int main()
{
int parent[VERTICES] = {0};
int rank[VERTICES] = {0};
int edges[6][2] = {
{0, 1}, {1, 2}, {1, 3},
{2, 4}, {3, 4}, {2, 5}
};
Init(parent, rank);
for(int i = 0; i < 6; ++i) {
int x = edges[i][0];
int y = edges[i][1];
if(Union(x, y, parent, rank) == 0) {
printf("Cycle detected!\n");
exit(0);
}
}
printf("No cycle found.\n");
return 0;
}
上面是一种路径压缩的思路,即根据 rank 数组,将较矮的树连接到较高的树上。
也有另一种路径压缩的方法,如下
int FindRoot(int x, int parent[])
{
int x_root = x;
while( x != parent[x]) {
x = parent[x]; // 此时 x 为根节点
}
// 进行路径压缩, 把所有非根节点的父节点都改为x
while(-1 != parent[x_root])
{
int z = x_root; // 先记录该节点
x_root = parent[x_root]; // a指向父节点
parent[z] = x; // 修改子节点的父亲
}
return x;
}
浙公网安备 33010602011771号