file transfer(文档传送程序)-并查集的应用

来源:互联网 发布:foxpro怎么建数据库 编辑:程序博客网 时间:2024/06/09 20:30

/*file transfer文档传送程序*/ typedef struct{//本数组的类型是结构体。集合的每个元素直接用数组里的下标去代表即可,此时数据域可以不要,直接定义一个整型数组即可表示集合。 ElementType Data;//数组有个结构域Data对应的是集合的元素的具体类型 (任何想要的类型)int Parent;//是个指针记录元素在数组里父结点的位置 }SetType; SetType S[];int Find(SetType S[],ElementType X){int i;//计算机从1~N编号,Data就成了整数。N个整数有必要开个数据域Data存它吗?for(i=0;i<MaxSize&&S[i].Data!=X;i++);/*找X是集合中是第几个元素 。首先要在数组里找到它(线性扫描过程),最坏情况是找数组里最后一个元素,反复找N遍,如果集合里有N个元素,把第N个反复找N遍。*/ //想知道集合元素X属于哪个集合。最坏情况时间复杂度为O(N*N),有点慢 if(i>MaxSize) return -1;for( ;S[i].Parent>=0;i=S[i].Parent);//从此位置检查它的父结点,>=0一直往上找,找到父结点为-1,返回i为根结点的下标 return i;}//每个元素对应的是数组的下标。例0结点父为6,所以S[0]=6typedef int ElementType;//集合的简化表示。默认元素可以用非负整数表示(0~N-1)typedef int SetName;//默认用根结点的下标作为集合名称 typedef ElementType SetType[MaxSize];//集合的类型是一个整型数组SetName Find(SetType S,ElementType X)//简化后的Find函数{//默认集合元素全部初始化为-1 for( ;S[X]>=0;X=S[X]) ;//S[X]是存放父结点,找到父结点为-1,返回X为根结点的下标  return X; }//查找元素X在哪里,先不需要扫描整个数组找到X,因为X是数组下标。void Union(SetType S,SetName Root1,SetName Root2){//这里默认Root1和Root2是不同集合的根结点/而判断参数合法性交给用户做 S[Root2]=Root1; } int main(){SetType S;//这是并查集,需要一个集合 int n;//是集合的元素个数 char in;//读每条指令,这条指令关键是第一个字符命名为inscanf("%d\n",&n);Initialization(S,n);//调用这个函数把S做初始化。do{scanf("%c\n",&in);//判断是哪种指令,直到in!='S'('S'是个终止符号) 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; } void Input_connection(SetType S)//输入指令   {ElementType u,v;SetName Root1,Root2;scanf("%d %d\n",&u,&v);Root1=Find(S,u-1);Root2=Find(S,v-1);if(Root1!=Root2)Union(S,Root1,Root2);}void Check_connection(SetType S)//查询指令   {ElementType u,v;SetName Root1,Root2;scanf("%d %d\n",&u,&v);Root1=Find(S,u-1);Root2=Find(S,v-1);if(Root1==Root2)printf("yes\n");else printf("no\n");  }void Check_network(SetTypeS,int n)//判断整个网络是否联通指令 {int i,counter=0;for(i=0;i<n;i++){if(S[i]<0) counter++;}if(counter==1)printf("The network is connected.\n");elseprintf("There are %d components.\n",counter); }/*按秩归并(1.按树高度2.按树规模)*/void Union_height(SetType S,SetName Root1,SetName Root2)//比树高 {//S[Root]=-树高;if(S[Root2]<S[Root1])//负数的比较 S[Root1]=Root2;else{if(S[Root1==Root2]) S[Root1]--;//正值+1,意味负值-1 S[Root2]=Root1;} }//最坏情况下的树高时间复杂度=O(logN) void Union_scale(SetType S,SetName Root1,SetName Root2)//比规模{//S[Root]=-元素个数; if(S[Root2]<S[Root1]){//因为存的是负数 S[Root2]+=Root1;//所以把集合2大小做改变,加上原来的集合1的规模 S[Root1]=Root2;//集合1指向集合2 } else{S[Root1]+=Root2;S[Root2]=Root1;}}//最坏情况下的树高时间复杂度=O(logN) /*路径压缩(对find函数优化)*/SetType Find(SetType S,ElementType X){if(S[X]<0)//找到集合的根return X;elsereturn S[X]=Find(S,S[X]); }  



0 0