实验目的:
在代码实践中,熟悉并查集的概念与应用,深入理解按秩归并与路径压缩算法,提高程序设计能力
预期效果:
首先输入终端个数n,然后将n个终端代号映射为0~n-1这n个整数,然后读入命令,命令分三种,分别为:"I a b"连通代号为a,b的终端,"C a b"检查代号为a,b的终端的连通性,"S"输出连通情况并结束程序。
实验思路:
将n个终端代号映射为0~n-1这n个整数后,使用并查集进行数据输入与存储。在读入终端命令后,使用switch-case语句搭建框架,并将各个命令效果分函数实现。
实验代码:
#include <stdio.h>
#include <stdlib.h>
/* 并查集实现 */
struct SNode {
int *data;
int maxSize;
};
typedef struct SNode *UFSet;
UFSet createUnionFindSet(int maxSize) {
UFSet S = (UFSet)malloc(sizeof(struct SNode));
S->data = (int *)malloc(maxSize*sizeof(int));
for (int i=0; i<maxSize; i++) {
S->data[i] = -1;
}
S->maxSize = maxSize;
return S;
}
int findRoot(UFSet S, int X) {
if (S->data[X]<0) {
return X;
}
else {
return S->data[X] = findRoot(S,S->data[X]);
}
}
void Union(UFSet S, int e1, int e2) {
int root1 = findRoot(S,e1);
int root2 = findRoot(S,e2);
if (S->data[root1]<S->data[root2]) {
S->data[root2] = root1;
}
else {
if(S->data[root1]==S->data[root2]) {
S->data[root2]--;
}
S->data[root1] = root2;
}
}
/* 并查集实现 完*/
/* 主程序 */
// 输入函数
void input(UFSet S) {
int e1,e2;
scanf("%d %d",&e1,&e2);
Union(S,e1,e2);
}
// 检查连通性函数
void check(UFSet S) {
int e1,e2;
scanf("%d %d",&e1,&e2);
if (findRoot(S,e1)==findRoot(S,e2)) {
printf("Yes\n");
}
else {
printf("No\n");
}
}
// 输出函数
void output(UFSet S) {
int cnt=0;
for (int i=0; i<S->maxSize; i++) {
if (S->data[i]<0) cnt++;
}
if (cnt==1) {
puts("所有终端均已连通。");
}
else {
printf("存在%d个未互相连通的部分\n",cnt);
}
}
int main() {
// 读入终端台数,初始化一个并查集
int n;
printf("请输入终端台数:");
scanf("%d",&n);
UFSet ufSet = createUnionFindSet(n);
// 读入指令
char command;
do {
scanf("%c",&command);
switch (command) {
case 'I': input(ufSet); break;
case 'C': check(ufSet); break;
case 'S': output(ufSet); break;
}
} while (command != 'S');
getchar();
getchar();
return 0;
}
测试结果: