并查集

定义

并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题(即所谓的并、查)。
主要由一个整型数组 p r e [ ] pre[] pre[]和函数 f i n d ( ) find() find() j o i n ( ) join() join()构成。
数组 p r e [ ] pre[] pre[]记录了每个点的前驱节点是谁。
函数 f i n d ( x ) find(x) find(x) 用于查找指定节点 x x x属于哪个集合。
函数 j o i n ( x , y ) join(x,y) join(x,y)用于合并 x x x y y y

find()函数

首先定义一个 p r e pre pre数组,记录着 i i i的上级是谁,例如 p r e [ 3 ] = 4 pre[3]=4 pre[3]=4,表示3的上级是4,若自己的上级是自己,则表示它是顶级了。
f i n d ( x ) find(x) find(x)函数的目的就是查找 x x x上级。

int find(int x)
{
	while(pre[x] != x)			//若x的上级不是自己,则说明还没找到
		x = pre[x];				//x继续找他的上级,直到找到最上级为止
	return x;					//找到了
}

join()函数

j o i n ( x , y ) join(x,y) join(x,y)是将x当作y的上级或者y当作x的上级。

void join(int x,int y)            
{
    int fx=find(x), fy=find(y);          //找到x与y的上级
    if(fx != fy)                         //发现并不是同一个上级
        pre[fx]=fy;                      //将y当作x的上级
}

总结:
附上抄袭代码一份(侵删)

const int  N=1005					//指定并查集所能包含元素的个数(由题意决定)
int pre[N];     					//存储每个结点的前驱结点 
int rank[N];    					//树的高度 
void init(int n)     				//初始化函数,对录入的 n个结点进行初始化 
{
    for(int i = 0; i < n; i++){
        pre[i] = i;     			//每个结点的上级都是自己 
        rank[i] = 1;    			//每个结点构成的树的高度为 1 
    } 
}
int find(int x)     	 		    //查找结点 x的根结点 
{
    if(pre[x] == x) return x;  		//递归出口:x的上级为 x本身,则 x为根结点 
    return find(pre[x]); 			//递归查找 
} 
 
int find(int x)     				//改进查找算法:完成路径压缩,将 x的上级直接变为根结点,那么树的高度就会大大降低 
{
    if(pre[x] == x) return x;		//递归出口:x的上级为 x本身,即 x为根结点 
    return pre[x] = find(pre[x]);   //此代码相当于先找到根结点 rootx,然后 pre[x]=rootx 
} 

bool isSame(int x, int y)      		//判断两个结点是否连通 
{
    return find(x) == find(y);  	//判断两个结点的根结点(即代表元)是否相同 
}

bool join(int x,int y)
{
    x = find(x);						//寻找 x的代表元
    y = find(y);						//寻找 y的代表元
    if(x == y) return false;			//如果 x和 y的代表元一致,说明他们共属同一集合,则不需要合并,返回 false,表示合并失败;否则,执行下面的逻辑
    if(rank[x] > rank[y]) pre[y]=x;		//如果 x的高度大于 y,则令 y的上级为 x
    else								//否则
    {
        if(rank[x]==rank[y]) rank[y]++;	//如果 x的高度和 y的高度相同,则令 y的高度加1
        pre[x]=y;						//让 x的上级为 y
	}
	return true;						//返回 true,表示合并成功
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值