并查集模板--C语言

并查集模板–C语言

#include <stdio.h>

//初始化并查集
void Initial(int S[],int size){
	for(int i=0;i<size;i++){
		S[i]=-1;
	}
} 

//Find "查"操作,找x所在集合(路径压缩)
int Find(int S[],int x){
	int root=x;
	while(S[root]>=0) root=S[root];//循环找到根
	while(x!=root){//压缩路径
	 	int t=S[x];//t指向x的父结点
		S[x]=root;//x直接挂到根节点下
		x=t; 
	} 
	return root;
} 
void Union(int S[],int Root1,int Root2){
	//找到两个结点的根节点
	Root1=Find(S,Root1);
	Root2=Find(S,Root2);
	if(Root1==Root2) return;//如果属于同一个集合那么不操作
	if(S[Root2]>=S[Root1]){//Root2结点数更少
		S[Root1]+=S[Root2];//累加结点总数 
		S[Root2]=Root1;//小数合并到大树
	}else{
		S[Root2]+=S[Root1];//累加结点总数 
		S[Root1]=Root2;//小树合并到大树 
	} 
}


并查集例题一:岛屿数量

Leecode第200道题

 //小岛数量 
int count;

//初始化并查集
void Initial(int S[],int size){
	for(int i=0;i<size;i++){
		S[i]=-1;
	}
} 

//Find "查"操作,找x所在集合(路径压缩)
int Find(int S[],int x){
	int root=x;
	while(S[root]>=0) root=S[root];//循环找到根
	while(x!=root){//压缩路径
	 	int t=S[x];//t指向x的父结点
		S[x]=root;//x直接挂到根节点下
		x=t; 
	} 
	return root;
} 
//Union "并操作",合并两个集合,小树合到大树
void Union(int S[],int Root1,int Root2){
	Root1=Find(S,Root1);
	Root2=Find(S,Root2);
	if(Root1==Root2) return;
	if(S[Root2]>=S[Root1]){//Root2结点数更少
		S[Root1]+=S[Root2];//累加结点总数 
		S[Root2]=Root1;//小数合并到大树
	}else{
		S[Root2]+=S[Root1];//累加结点总数 
		S[Root1]=Root2;//小树合并到大树 
	} 
     --count;//每一次合并都是两个岛合并为一个岛
}

//统计岛屿数量
int numIslands(char** grid, int gridSize, int* gridColSize){
	int colSize=gridColSize[0];//列大小 
	int size=colSize*gridSize;//岛屿数组大小
	count=0;//初始化小岛数量
	int UFSets[size];//并查集数组
	Initial(UFSets,size);//初始化数组 
   
	//遍历整个岛屿数组,进行合并操作 
	for(int i=0;i<gridSize;i++){
		for(int j=0;j<colSize;j++){
			if(grid[i][j]=='1'){
                ++count;//每一个1都是一个小岛
                grid[i][j]=='0';
                int root1;//结点1
			    int root2;//结点2
                if(i-1>=0&&grid[i-1][j]=='1'){//上合并 
                    root1=(i-1)*colSize+j;
				    root2=i*colSize+j;
			    }
                if(j-1>=0&&grid[i][j-1]=='1'){//左合并
				    root1=i*colSize+j-1;
				    root2=i*colSize+j;
			    }
                if(i+1<gridSize&&grid[i+1][j]=='1'){//下合并 
				    root1=(i+1)*colSize+j;
				    root2=i*colSize+j;
			    }
                if(j+1<colSize&&grid[i][j+1]=='1'){//右合并 
				    root1=i*colSize+j+1;
				    root2=i*colSize+j;
			    }
			    Union(UFSets,root1,root2);
            }
		} 
	} 
	return count;
}

并查集例题二:无向图的连通性

#include <stdio.h>
#include<stdlib.h> 

//初始化并查集
void Initial(int S[],int size){
	for(int i=0;i<size;i++){
		S[i]=-1;
	}
}
//查操作,路径压缩 
int Find(int S[],int x){
	int root=x;
	while(S[root]>-1) root=S[root];//找到x的根节点
	while(x!=root){//路径压缩
		 int parent=S[x];
		 S[x]=root;
		 x=parent;
	}
	return root; 
} 
//并操作,合并集合
bool Union(int S[],int root1,int root2){
	root1=Find(S,root1);
	root2=Find(S,root2);
	if(root1==root2) return false;
	if(S[root1]<=S[root2]){
		S[root1]+=S[root2];
		S[root2]=root1;
	}else{
		S[root2]+=S[root1];
		S[root1]=root2;
	}
	return true;
} 
//无向连通图是否成环 
bool graphIsCircle(int** graph,int row,int col){
	int UFsets[row];//并查集数组 
	Initial(UFsets,row);//初始化并查集数组 
	
	for(int i=0;i<row;i++){
		for(int j=i+1;j<col;j++){
			//循环遍历无向图 
			if(graph[i][j]==1&&!Union(UFsets,i,j)){
				return false;
			}
		}
	}
	return true;
}
int main(){
	//定义图的邻接矩阵 
	int row=4;
	int col=4;
	int** graph=(int **)malloc(sizeof(int *)*row);
	for(int i=0;i<row;i++){
		graph[i]=(int *)malloc(sizeof(int)*col);
	}
	//初始化图 
	graph[0][0]=0;
	graph[0][1]=1;
	graph[0][2]=0;
	graph[0][3]=1;
	
	graph[1][0]=1;
	graph[1][1]=0;
	graph[1][2]=1;
	graph[1][3]=0;
	
	graph[2][0]=0;
	graph[2][1]=1;
	graph[2][2]=0;
	graph[2][3]=1;
	
	graph[3][0]=0;
	graph[3][1]=0;
	graph[3][2]=1;
	graph[3][3]=0;
	printf("图是否成环: %d",graphIsCircle(graph,row,col));
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值