前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >动态联通性问题----union-find算法

动态联通性问题----union-find算法

作者头像
SuperHeroes
发布2018-05-30 17:42:04
6260
发布2018-05-30 17:42:04
举报
文章被收录于专栏:云霄雨霁云霄雨霁

定义union-find算法API:

public class UF{               UF(int N)                          初始化N个触点       void union(int p,int q)            在p和q之间建立连接          int find(int p)                        p所在的分量的标识符 boolean connected(int p,int q)     p和q同在一个分量中则为true          int count()                             连通分量的数量 }

初始状态,每个触点都是一个分量。两点之间建立连接后,union()方法会将两个分量合并,一个分量中各触点都相互连接。find()方法返回给定触点所在连通分量的标识符。

此份API中,构造函数和count()方法很好写,connected方法只含有一条语句,即return find(p)==find(q);

数据结构:采用数组来实现。初始时数组各个元素保存自己的下标。

所以关键是实现find()方法和union方法。

1、quick-find算法

quick-find算法保证在同一连通分量中所有触点id[]中的值必须相同,这样connected()方法只需判断id[p]==id[q]即可。

find方法只需return id[p]; 而将两个连通分量合并,union()必须遍历数组,将一个连通分量中的id[]值变为另一个连通分量的id[]值。

代码语言:javascript
复制
public int qk_find(int p) {
	return id[p];
}
	
public void qf_union(int p,int q) {
	int pID = qk_find(p);
	int qID = qk_find(q);
	if(pID == qID) return;
	for(int i = 0;i<id.length;i++)
		if(id[i] == pID) id[i] = qID;
	count--;
}

算法分析:

在quick-find算法中,每次find()调用访问一次数组,归并两个分量的union()操作访问数组次数在(N+3)到(2N+1)之间。

假设最后只得到一个连通分量,至少需要N-1次union操作,(N+3)*(N-1)~N^2, 算法是平方级别的。

2、quick-union算法

quick-union算法中每个触点所对应的id[]元素都是另一个触点的名称(也可能是自己,如果是自己的画说明是根触点),触点之间循环这种关系直到到达根触点。当且仅当两个触点开始这个过程打到同一个根触点说明它们存在于一个连通分量中。

find()方法就是沿着这条路径找到根节点。union()方法只需将一个根节点链接到另一个上面就可实现合并分量。每个分量其实都是一个多叉树。

代码语言:javascript
复制
public int qu_find(int p) {
	while(p!=id[p]) p=id[p];
	return p;
}
	
public void qu_union(int p,int q) {
	int pRoot = qu_find(p);
	int qRoot = qu_find(q);
	if(pRoot == qRoot) return;
	id[pRoot] = qRoot;
	count--;
}

算法分析:

find()方法访问数组次数是1+触点所在树的高度*2;union()和connected()为两次。

算法改进(加权quick-union算法):

保证小的树链接在大树上,即给每一个分量添加权重。

在类中新建一个数组保存各根节点的权重,注意该数组只有只有根结点对象的下标中的数据有效。然后修改union方法如下:

代码语言:javascript
复制
public void wei_union(int p,int q) {
	int i = qu_find(p);
	int j = qu_find(q);
	if(i == j) return;
	if(sz[i]<sz[j]) {id[i]=j;sz[j]+=sz[i]}
	else {id[j]UF = i; sz[i]+=sz[j];}
	count--;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.12.11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档