浙大数据结构习题笔记:05-树8 File Transfer (25分)

05-树8 File Transfer (25分)

原题


在这里插入图片描述
在这里插入图片描述

总结

这道题就是并查集的配套习题,之前学校在学图的算法时就提到过要使用并查集实现,但因为没细讲并查集的实现导致我学的一知半解(
学完这个后,觉得还可以,这里面的并查集还是比较好实现的,通过数组下标记录对应值,数组中存储的是每个值的父节点的位置。FindUnion采用极简的操作如下

int Find(SetType S[],int n)
{
	for(;S[n] >= 0;n = S[n]);
	return x;
}

void Union(SetType s[],int x1,int x2){
	S[x2] = S[x1];
}

但是以这样的极简方法来做,可能会造成超时
于是我们采用按秩归并路径压缩的方法简化时间,具体操作如下程序
其中的按秩归并,我们设根节点的值为-元素个数,就是值为这个根下面所有元素个数的负数,如果根后无节点,就是-1,以这样的方式,我们可以做到在归并的过程中,将元素少的根节点并到元素多的根结点上,使得树的高度不会必然增加

在路径压缩中,我们采用一个尾递归的方式,在递归过程中将一个高度很高的树打散,分别接在第一个节点上,具体作用如图

在这里插入图片描述

具体代码实现

#include<cstdio>
#define MaxSize 10005
typedef int SetType; 
using namespace std;

void Init(SetType s[],int n){
	for(int i=0;i<n;i++)
		s[i] = -1;
}

int Find(SetType s[],int x){
	if(s[x] < 0)  // 本身已经是根 
		return x;
	else  // 1. 找到根  2. 把根变成 x 的父结点  3.再返回根 
		return s[x] = Find(s,s[x]);
} 

void Union(SetType s[],int x1,int x2){
    //S[root] = -元素个数
    if(s[x1] < s[x2]){  //x1的元素多,少的并入多的中
		s[x1] += s[x2];
		s[x2] = x1;
	}else{
		s[x2] += s[x1];
		s[x1] = x2;
	}
} 

void Input_connection(SetType s[]){
	int x1,x2;
	scanf("%d %d",&x1,&x2);
	int root1 = Find(s,x1-1);  // 以数组下标存值,下标与存值差 1 
	int root2 = Find(s,x2-1);
	if(root1 != root2)
		Union(s,root1,root2);
}

void check_connection(SetType s[]){
	int x1,x2;
	scanf("%d %d",&x1,&x2);
	int root1 = Find(s,x1-1);
	int root2 = Find(s,x2-1);
	if(root1 == root2)
		printf("yes\n");
	else
		printf("no\n");
} 

void check_network(SetType s[],int n){
	int counter = 0;
	for(int i=0;i<n;i++)
		if(s[i] < 0)
			counter++;
	if(counter == 1)
		printf("The network is connected.");
	else
		printf("There are %d components.",counter);
}


int main(){
	int n;
	char in;
	scanf("%d",&n); 
	SetType s[MaxSize];
	Init(s,n);
	do{
		getchar();
		scanf("%c",&in);
		switch(in){
			case 'I':Input_connection(s);break;
			case 'C':check_connection(s);break;
			case 'S':check_network(s,n);break;
		}		
	}while(in != 'S');

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值