数据结构 5-4-1 并查集

一、概念

并查集本质上是对树的知识的利用,常用于集合的相关表示,不同于一般的二叉树,并查集用的是指向双亲节点的指针,便于分类而不便于找子节点,

二、代码实现

简单的并查集主要有三个函数,初始化、合并、查询。

初始化有很多种方法。可以全部初始化为自己,相当于开始状态看做每个节点都是单独的一棵树,这些树只有一个根节点,让其都指向自己。也可以全部初始化为-1.这种初始化的好处是可以在最顶上的节点保存这个集合有多少个节点。

void init()
{
    
    
	for(int i=1;i<=n;i++)
		data[i]=i;
}
//初始化为自己
void init()
{
    
    
	for(int i=1;i<=n;i++)
		data[i]=-1;
}
//初始化为-1

合并根据初始化的方式不同,也有细微的差别,但主要思路都是一样的,比较两个节点是不是在一个集合里,如果不在,说明可以合并,用查找函数找到集合的根节点,然后让一个根节点指向另一个,就可以完成合并的操作。

void merge(int x,int y)
{
    
    
	int tx=find(x);
	int ty=find(y);
	if(tx!=ty)
		data[tx]=data[ty];
	//初始化为-1时可以补一句data[ty]+=data[tx],这样数组值的绝对值表示的就是集合中元素的个数
}

查找根据初始化的不同,应该设置不同的查找结束标志。采用初始化为自己时,查找结束的标志是对应位置的值等于自己的下标。初始化为-1时,查找结束的标志是对应位置的值小于零。

int find(int x)
{
    
    
	while(data[x]!=x)
		x=data[x];
	return x;
}
//初始化为自己
int find(int x)
{
    
    
	while(data[x]>=0)
		x=data[x];
	return x;
}
int find(int n)
{
    
    
	if(pre[n]==n)
		return n;
	else
		return pre[n]=find(pre[n]);
}
//递归实现

并查集本身不难,前面搞蓝桥ACM时学长都说不难,理解好向上查找的这个过程即可。完整代码如下

#include<bits/stdc++.h>
using namespace std;
int data[1005];
int m,n,choice=0;
void init()
{
    
    
	for(int i=1;i<=n;i++)
		data[i]=i;
}
int find(int x)
{
    
    
	while(data[x]!=x)
		x=data[x];
	return x;
}
void merge(int x,int y)
{
    
    
	int tx=find(x);
	int ty=find(y);
	if(tx!=ty)
		data[tx]=data[ty];
}
int main()
{
    
    
	scanf("%d %d",&m,&n);
	init();
	for(int i=0;i<m;i++)
	{
    
    
		int x,y;
		scanf("%d %d",&x,&y);
		merge(x,y);
	}
	scanf("%d",&choice);
	while(choice!=-1)
	{
    
    
		printf("%d\n",find(choice));
		scanf("%d",&choice);
	}
		 
	return 0;
 } 

猜你喜欢

转载自blog.csdn.net/weixin_43849505/article/details/107499141