赞
踩
并查集广泛应用于图和树一些基本操作,如给定一个网络的连接,{ connections = [[0,1],[0,2],[1,2]] }可以判定网络中每台计算机是否可以相接(即森林中有几棵树)。
本文第一部分用【数组】实现并查集,并配合一道leecode题来进行应用。第二部分为优化的并查集,同时配合一道leetcode来检验
1.用数组来实现并查集。数组中有两种节点:值为 -1,即为数组(有可能是一个节点);值为正值,该值即为父节点的index。
题目请参考leetcode 1319 题:
1319. 连通网络的操作次数
void ds_init(int *data,int length){ int i=0; for(i=0;i<length;i++){ data[i]=-1; } } int ds_find(int *data,int length,int num){ if(data[num]==-1) return num; else{ int temp=num; while(data[temp]!=-1){ temp=data[temp]; } return temp; } } void ds_union(int *data,int length,int first,int second){ int p1=ds_find(data,length,first); int p2=ds_find(data,length,second); if(p1==p2) return; data[p2]=p1; return; } //1.Traverse the 2-D array to determine whether two points belong to a set; //2.Belong to a set,union,[line] plus one; otherwise,union. Mark the two points; //3.compare the number of [line] and unmarked points //patch: compare root and [line] int makeConnected(int n, int** connections, int connectionsSize, int* connectionsColSize){ //init int data[n]; int flag[n]; int line=0; int unlabel=n; //计算未标记的值不正确。因为可能有多颗树,树之间也要连接 int root=0; //使用root 来标记待连接的点 int i=0,j=0; int row=connectionsSize; int col=(*connectionsColSize); int forset=0; int first=0,second=0; int ** p=connections; for(i=0;i<n;i++){ data[i]=-1; flag[i]=-1; } ds_init(data,n); //step 1 for(i=0;i<row;i++){ first=p[i][0]; second=p[i][1]; int r1=ds_find(data,n,first); int r2=ds_find(data,n,second); //step 2 if(r1==r2){ ds_union(data,n,first,second); line++; } else{ ds_union(data,n,first,second); } flag[first]=1; flag[second]=1; } //step 3 for(i=0;i<n;i++){ //if(flag[i]==1) // unlabel--; if(data[i]==-1) root++; } if(line>=(root-1)){ return root-1; } else return -1; } /* int main(){ int conn[4][2]={{0,1},{0,2},{3,4},{2,3}}; int n=5; int * p[4]; p[0]=conn[0]; p[1]=conn[1]; p[2]=conn[2]; p[3]=conn[3]; int row=4; int col=2; int ret=makeConnected(n,p,row,&col); printf("answer = %d\n",ret); } */
有个case 通不过(20220126已通过)。调试时候输入麻烦,可以用case下面几行代码替换方括号:
s1=s.replace('[','{')
s2=s1.replace(']','}')
print(s2)
2.优化及leetcode 547。
//the depth of root is -1.e.g. -3 means the depth of the root is 3 void ds_init_opti(int *data,int length){ int i=0; for(i=0;i<length;i++){ data[i]=-1; } } int ds_find_opti(int *data,int length,int num){ if(data[num]==-1) return num; else{ return data[num]=ds_find_opti(data,length,data[num]); } } void ds_union_opti(int *data,int length,int first,int second){ int root1=ds_find_opti(data,length,first); int root2=ds_find_opti(data,length,second); if(root1==root2) return; int d1=data[root1]; int d2=data[root2]; if(d1<d2){ //root1 deeper data[root2]=root1; } else{ //root2 deeper data[root1]=root2; } return; } //1.traverse 2-D array p[i][j],data[n] set to -1 //2.if p[i][j]==1 union(i,j) marked(i,j);else continue //3.calculate data[n] number of -1 int findCircleNum(int** isConnected, int isConnectedSize, int* isConnectedColSize){ int row=isConnectedSize; int col=(*isConnectedColSize); int **p=isConnected; int i=0,j=0; int n=row; int data[n]; int ret=0; for(i=0;i<n;i++) data[i]=-1; //step 1 for(i=0;i<row;i++){ for(j=0;j<col;j++){ //step 2 if((i==j)||(p[i][j]==0)){ continue; } else{ int t1=ds_find_opti(data,n,i); int t2=ds_find_opti(data,n,j); if(t1!=t2){ ds_union_opti(data,n,i,j); } } } } //step 3 for(i=0;i<n;i++){ if(data[i]==-1) ret++; } return ret; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。