#include <stdio.h>
//并查集操作实现(顺序存储,双亲表示法实现)
//并查集的操作主要有两个
//1)查找某个元素属于哪个集合
//2)合并两个集合
#define MAX_SIZE 100
typedef struct ElemType {
char value;
} ElemType;
typedef struct {
ElemType data;
int parent;
} Node;
typedef struct {
Node sets[MAX_SIZE];
int n;
} UFSets;
//初始化
void Initial(UFSets &S, int size) {
for (int i = 0; i < size; ++i) {
S.sets[i].data = {};
S.sets[i].parent = -1;
}
S.n = size;
}
查找某个元素的属于哪个集合
//Node Find(Node S[], Node x) {
// if (x.parent == -1)
// return x;
// while (x.parent != -1) {
// x = S[x.parent];
// }
// return x;
//}
合并两个结合
//void Union(UFSets &S, int index1, int index2) {
// Node &root1 = S.sets[index1];
// Node &root2 = S.sets[index2];
// if(root1.parent != -1 ||
// root2.parent!=-1) {//不是集合
// return;
// }
// if (root1.data.value == root2.data.value
// && root1.parent == root2.parent) {//相同的集合
// return;
// } else {
// root2.parent = index1;
// }
//}
//并操作的优化:小树合并到大树
//该方法构造的树高不超过 log2(n)下取整 +1
void Union(UFSets &S, int index1, int index2) {
Node &root1 = S.sets[index1];
Node &root2 = S.sets[index2];
if (root1.parent >= 0 ||
root2.parent >= 0) {//不是集合
return;
}
if (root1.data.value == root2.data.value
&& root1.parent == root2.parent) {//相同的集合
return;
} else {
//小树合并到大树
if (root1.parent >= root2.parent) {
root2.parent += root1.parent;
root1.parent = index2;
} else {
root1.parent += root2.parent;
root2.parent = index1;
}
}
}
查找某个元素的属于哪个集合
通过小树合并大树的操作,查找最坏时间复杂度log2(n)
//Node Find(Node S[], Node x) {
// if (x.parent <0)
// return x;
// while (x.parent >=0) {
// x = S[x.parent];
// }
// return x;
//}
//查找某个元素的属于哪个集合 路径压缩优化,即某次查找把所有查找到的元素挂到根元素下面
Node Find(UFSets &S, int i) {
Node x = S.sets[i];
//循环找到根
if (x.parent < 0)
return x;
Node root = x;
int rootIndex = 0;
while (root.parent >= 0) {
rootIndex = root.parent;
root = S.sets[root.parent];
}
while (x.parent >= 0) {
S.sets[i].parent = rootIndex;//已经访问的元素挂到根元素下面
i = x.parent;
x = S.sets[i];
}
return root;
}
int main() {
UFSets S;
Initial(S, 13);
//添加一些元素
//创建集合 A
Node A, B, C, D, E, F, G, H, I, J, K, L, M;
A.parent = -6;
C.parent = -2;
D.parent = -5;
A.data = {'A'};
S.sets[0] = A;
B.data = {'B'};
B.parent = 0;
S.sets[1] = B;
//创建集合 C
C.data = {'C'};
S.sets[2] = C;
//创建集合 D
D.data = {'D'};
S.sets[3] = D;
E.data = {'E'};
E.parent = 1;
S.sets[4] = E;
F.data = {'F'};
F.parent = 1;
S.sets[5] = F;
G.data = {'G'};
G.parent = 2;
S.sets[6] = G;
H.data = {'H'};
H.parent = 3;
S.sets[7] = H;
I.data = {'I'};
I.parent = 3;
S.sets[8] = I;
J.data = {'J'};
J.parent = 3;
S.sets[9] = J;
K.data = {'K'};
K.parent = 4;
S.sets[10] = K;
L.data = {'L'};
L.parent = 4;
S.sets[11] = L;
M.data = {'M'};
M.parent = 7;
S.sets[12] = M;
Node X = M;
int index = 11;
//查找 M
Node Y = Find(S, index);
printf("%c属于集合%c\n", X.data.value, Y.data.value);
//合并 A C两个集合
Union(S, 0, 3);
// 查找 M
Y = Find(S, index);
printf("%c属于集合%c\n", X.data.value, Y.data.value);
return 0;
}
数据结构复习:并查集基本操作实现
最新推荐文章于 2023-08-24 10:56:42 发布