输入数据是N个集合的类,每个集合含有一个元素。
每个集合都有一个不同的元素,从而Si∩Sj= Ø;使得这些集合不相交。
此时,有两种运算允许运行。find()返回包含给定元素的集合的名字,第二种是添加关系,如果想要添加关系(a,b)
首先查看a和b是否已经有关系,对a和b执行find并检验它们是否在一个集合,若不在一个集合,使用并运算Union(),这种运算把含有a和b的集合合并为一个集合。
基本数据结构:用一个数组来记录元素的父节点。数组中的每个成员P[i]表示元素i的父亲,集合的名字有根处的节点给出。
若P[i]为负值,表示该集合的规模,如-1为集合中有一个元素。
为了执行两个集合的Union运算,使一个节点的根指针指向另一个树的根节点。
对元素X的一次Find(X)操作通过返回包含X的树的根而完成。
#include<stdio.h>
#define MAXNUM 100
//初始化P数组
void Initilalize(int P[],int N) {
//N为节点的个数
int i;
for (i = 0; i < N; i++)
P[i] = -1;
}
// 查找元素X 属于的集合
int Find(int P[], int X)
{
if (P[X] < 0)
{
return X; // 如果X中内容为负值,代表X就是根节点
}
else
{
return P[X] = Find(P, P[X]); // 继续查找,并返回查找到的集合,进行路径压缩
}
}
void Union(int x,int y,int P[]) {
int x_root, y_root;
x_root = Find(P, x);
y_root = Find(P, y);
if (x_root == y_root) // 属于同一个集合,什么也不做
{
return;
}
else
{
if (P[x_root] < P[y_root]) // 按集合中的规模大小进行合并,x_root集合大
{
P[x_root] += P[y_root]; // x_root集合更新规模
P[y_root] = x_root; //y_root集合更新根节点
}
else
{ //y_root的集合大
P[y_root] += P[x_root]; // y_root集合更新规模
P[x_root] = y_root; // x_root集合更新根节点
}
}
}
int CheckCycle(int P[], int x, int y) // 判断两个顶点是否相连,不相连合并集合
{
int x_root, y_root;
x_root = Find(P, x);
y_root = Find(P, y);
if (x_root == y_root)
{
return 1;
}
else
{
Union(x_root, y_root, P);
return 0;
}
}