数据结构课程设计-检查网络(并查集)

检查网络

给定一个计算机网络以及机器间的双向连线列表,每一条连线与允许两端的计算机进行直接的文件传输,其他计算机间若存在一条连通路径,也可以进行间接的文件传输。

要求实现功能:

任意指定两台计算机,判断整个网络中是否任意两台机器间都可以文件传输?若不可以,请给出当前网络中连通分量的个数及各个连通分量中的机器。 增加两台计算机之间的连线。

基本要求:

至少使用两种结构实现。

 

数组实现:

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1000
using namespace std;

int cc[maxn];  //用来记录每个连通分量中的一个值,cc[1]=3:第一个连通分量中的一个值为3
int par[maxn],ran[maxn],a[maxn],b[maxn];

void Init(int n)  //初始化
{
    for(int i=0;i<=n;++i){
        par[i] = i;
        ran[i] = 0;
    }
}
int Find_par(int x)  //寻找父节点
{
    if(par[x]==x) return x;
    return par[x] = Find_par(par[x]);
}
void Unite(int x,int y)   //可连接的计算机了相连
{
    int fx = Find_par(x);
    int fy = Find_par(y);
    if(fx == fy) return ;
    if(ran[fx]<ran[fy])
        par[fx] = fy;
    else{
        par[fy] = fx;
        if(ran[fx]==ran[fy])
            ran[fx]++;
    }
}
int Acount(int n)  //计算连通分量个数
{
    int cnt=0,flag = 1,k;
    for(int i=1;i<=n;++i){
        if(Find_par(i)==i){
			cnt++;
			cc[cnt] = i;
		}
    }
    return cnt;
}
int main()
{
    int n,m,ans,mac1,mac2;
    char op;
    while(n|m){
        printf("请输入计算机的数量:");
        scanf("%d",&n);
        printf("请输入可直接相连的计算机的对数:");
        scanf("%d",&m);
        if(n>maxn||m>maxn){
            printf("\n数据越界,请重新输入!!!\n\n\n");
            continue ;
        }
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        Init(n);
        printf("请输入可直接相连的计算机机号:\n");
        for(int i=1;i<=m;++i){
            scanf("%d %d",&a[i],&b[i]);
            Unite(a[i],b[i]);
        }
        while(1){
            printf("请输入想要的操作(Q:查询连通情况,A:增加连线 ,N:退出):");
            cin>>op;
            if(op == 'Q'){  //查询
                ans = Acount(n);
                if(ans == 1){
                    printf("任意两台计算机均可连通\n");
                }
                else{
                    printf("连通分量的个数为: %d\n",ans);
                    for(int i=1;i<=ans;i++){
                        printf("第%d个连通分量中的机器有 : ",i);
                        for(int j=1;j<=n;++j){
                            if(Find_par(cc[i])==Find_par(par[j]))
                                printf("%d ",j);
                        }
                        printf("\n");
                    }
                    printf("请输入两台计算机序号,判断其二者是都可以连通:(以0,0结束)\n");
                    while(scanf("%d %d",&mac1,&mac2)){
                        if(mac1+mac2==0) break;
                        if(Find_par(mac1) == Find_par(mac2)) printf("%d号计算机与%d号计算机可以连通\n",mac1,mac2);
                        else printf("二者无法连通\n");
                    }
                }
            }
            else if(op == 'A'){  //添加连接
                int num;
                printf("请输入添加的连线数:\n");
                scanf("%d",&num);
                printf("请输入新添加连线的机器号:\n");
                while(num--){
                    scanf("%d %d",&mac1,&mac2);
                    Unite(mac1,mac2);
                }
                continue;
            }
            else break;
        }
        printf("\n\n");
    }
    return 0;
}
/*
10 9

1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
输出结果:
任意两台计算机均可连通

10 7

1 2
1 3
1 5
1 9
4 6
4 7
8 10

输出结果:
连通分量的个数为: 3
第1个连通分量中的机器有 : 1 2 3 5 9
第2个连通分量中的机器有 : 4 6 7
第3个连通分量中的机器有 : 8 10

10 5

1 2
1 4
2 6
4 7
3 5

输出结果:
连通分量的个数为: 5
第1个连通分量中的机器有 : 1 2 4 6 7
第2个连通分量中的机器有 : 3 5
第3个连通分量中的机器有 : 8
第4个连通分量中的机器有 : 9
第5个连通分量中的机器有 : 10

10 3

1 10
2 8
8 10
输出结果:
连通分量的个数为: 7
第1个连通分量中的机器有 : 1 2 8 10
第2个连通分量中的机器有 : 3
第3个连通分量中的机器有 : 4
第4个连通分量中的机器有 : 5
第5个连通分量中的机器有 : 6
第6个连通分量中的机器有 : 7
第7个连通分量中的机器有 : 9


10 6

1 2
1 3
3 8
8 10
4 5
6 7
输出结果:
连通分量的个数为: 4
第1个连通分量中的机器有 : 1 2 3 8 10
第2个连通分量中的机器有 : 4 5
第3个连通分量中的机器有 : 6 7
第4个连通分量中的机器有 : 9
*/

结构体实现:

#include <iostream>
#include <cstdio>
#define maxn 1000
using namespace std;


int cc[maxn]; //连通分量
struct node
{
	int data;
	int ran;
	int parent;
}t[maxn];

void Init(int n)
{
	for(int i=1;i<=n;++i)
	{
		t[i].data = i;
		t[i].ran = 0;
		t[i].parent = i;
	}
}
int Find_par(int x)
{
    if(t[x].parent==x) return x;
    return t[x].parent = Find_par(t[x].parent);
}
void Unite(int x,int y )
{
	x=Find_par(x);
	y=Find_par(y);
	if(x==y) return ;
	if( t[x].ran < t[y].ran )
		t[x].parent=y;
	else{
		t[y].parent=x;
		if( t[x].ran==t[y].ran)
			t[x].ran++;
	}
}
int Acount(int n)
{
    int cnt=0,flag = 1,k;
    for(int i=1;i<=n;++i){
        if(t[i].parent == i){
			cnt++;
			cc[cnt] = i;
		}
    }
    return cnt;
}
int main()
{
    int n,m,ans,mac1,mac2;
    char op;
    while(n|m){
        printf("请输入计算机的数量:");
        scanf("%d",&n);
        printf("请输入可直接相连的计算机的对数:");
        scanf("%d",&m);
        if(n>maxn||m>maxn){
            printf("\n数据越界,请重新输入!!!\n\n\n");
            continue ;
        }
        Init(n);
        printf("请输入可直接相连的计算机机号:\n");
        for(int i=1;i<=m;++i){
            scanf("%d %d",&mac1,&mac2);
            Unite(mac1,mac2);
        }
       while(1){
            printf("请输入想要的操作(Q:查询连通情况,A:增加连线 ,N:退出):");
            cin>>op;
            if(op == 'Q'){  //查询
                ans = Acount(n);
                if(ans == 1){
                    printf("任意两台计算机均可连通\n");
                }
                else{
                    printf("连通分量的个数为: %d\n",ans);
                    for(int i=1;i<=ans;i++){
                        printf("第%d个连通分量中的机器有 : ",i);
                        for(int j=1;j<=n;++j){
                            if(Find_par(cc[i])==Find_par(t[j].parent))
                                printf("%d ",j);
                        }
                        printf("\n");
                    }
                    printf("请输入两台计算机序号,判断其二者是都可以连通:(以0,0结束)\n");
                    while(scanf("%d %d",&mac1,&mac2)){
                        if(mac1+mac2==0) break;
                        if(Find_par(mac1) == Find_par(mac2)) printf("%d号计算机与%d号计算机可以连通\n",mac1,mac2);
                        else printf("二者无法连通\n");
                    }
                }
            }
            else if(op == 'A'){  //添加连接
                int num;
                printf("请输入添加的连线数:\n");
                scanf("%d",&num);
                printf("请输入新添加连线的机器号:\n");
                while(num--){
                    scanf("%d %d",&mac1,&mac2);
                    Unite(mac1,mac2);
                }
                continue;
            }
            else break;
        }
        printf("\n\n");
    }
    return 0;
}

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值