算法起步之并查集(不相交集合数据结构)

简介: 原文: 算法起步之并查集(不相交集合数据结构)          在java中经典的数据结构基本都给实现好了,我们可以直接调用,但是并查集这种数据结构却没有很好的替代工具,在这里我们我们自己去实现并查集数据结构。
原文: 算法起步之并查集(不相交集合数据结构)

         在java中经典的数据结构基本都给实现好了,我们可以直接调用,但是并查集这种数据结构却没有很好的替代工具,在这里我们我们自己去实现并查集数据结构。首先我们先要去了解什么是并查集。并查集也是一种非常经典常用的数据结构。像求连通子图跟我们下面要研究的最小生成树问题都会用到并查集。并查集就是能够实现若干个不相交集合,较快的合并和判断元素所在集合的操作。不相交集合:一个不相交集合维护了一个不相交动态集合{s1,s2,s3……}我们用一个代表标示每一个集合,他是这个集合的成员。我们不关心哪个成员作为代表,仅关心2次查询这个集合时放回结果应该相同(如果我们不修改集合)。

    并查集主要就有三个方法:

    make-set(x)建立一个新集合唯一元素就是x,因为是不相交集合所以x不会出现在其他集合中。

    union(x,y)将包含x和y的2个动态集合合并成一个新集合。

    find-set(x)返回一个指针,这个指针指向包含x的集合的代表。

    这样说是不是有点懵,我们来看一个图。


       

        上图两棵树就是一个不相交集合,a数的代表就是a而e树代表就是e我们在a树上查找b则返回a而查找c也返回a说明b与c在同一结合上,而查找f返回e,说明b与e是在两个结合上,他们两个是不相交的。而union操作就是将两颗树合并成一棵树。

     我们先给出一个一般的实现,数组表示不相交集合保存的各个集合的元素。初始化时:


           每个元素都指向自己的父节点也就是自己。这种方式每个节点都指向自己的上一节点。而只有代表节点指向的是自己。所以我们根据这个来搜索代表节点。

public class Ufsarry {

	
	private int[] node;
	private int max;
	public void makeset(int n){
		node=new int[n+1];
		max=n;
		//所有的节点都是不相交集合,代表节点都指向自己。
		for (int i = 0; i < node.length; i++) {
			node[i]=i;
		}
	}
	public int findset(int x){
		while (x!=node[x]) {
			x=node[x];
		}
		return x;
	}
	public void union(int x,int y){
		node[x]=y;
	}
}
           下面我们要说的就是并查集的优化,按秩合并与路径压缩。听着好像很高深,其实很哄人的。两张图就可以解释。



            第一张图就是路径压缩,我们之前都是指向的上一节点,而压缩则是直接指向代表节点。而按秩合并则是我们外加一个属性来记录集合的秩。而秩多的则说明树比较高,我们将矮的树嫁接在高的树上,这样总的高度较小。而如果高度相同,则只需要将一个树嫁接过去,给他的秩加一即可。

public class Ufs {
	
	private int[] father;
	private int[] rank;
	
	public void makeset(int x){
		father[x]=x;
		rank[x]=0;
	}
	public int findset(int x){
		if (father[x]!=x) {
			father[x]=findset(father[x]);
		}
		return father[x];
	}
	
	public void union(int x,int y){
		x=findset(x);
		y=findset(y);
		if (x==y) {
			return;
		}else {
			if (rank[x]>rank[y]) {
				father[y]=x;
			}else{
				if (rank[x]==rank[y]) {
					rank[y]++;
				}
				father[x]=y;
			}
		}
	}


}


        优化后的代码并不比之前的代码复杂。我们这里是用的数组来实现的,当然也可以用链表来实现。我们下面要说的Kruskal算法的效率就要看,我们写的并查集的实现。而按秩合并与路径压缩是目前已知渐进时间最快的Kruskal算法实现方式。

友情提示:转载请注明出处【作者idlear    博客http://blog.csdn.net/idlear/article/details/19556587】


目录
相关文章
|
25天前
|
算法 C++ Windows
空间射线与三角形相交算法的两种实现
空间射线与三角形相交算法的两种实现
14 0
|
18天前
|
Java
【Java集合类面试二十六】、介绍一下ArrayList的数据结构?
ArrayList是基于可动态扩展的数组实现的,支持快速随机访问,但在插入和删除操作时可能需要数组复制而性能较差。
|
17天前
|
存储 安全
集合的特点和数据结构总结
集合的特点和数据结构总结
13 1
|
20天前
|
算法
【初阶数据结构】复杂度算法题篇
该方法基于如下的事实:当我们将数组的元素向右移动 k 次后,尾部 kmodn 个元素会移动至数组头部,其余元素向后移动 kmodn 个位置。
|
21天前
|
机器学习/深度学习 人工智能 算法
【人工智能】线性回归模型:数据结构、算法详解与人工智能应用,附代码实现
线性回归是一种预测性建模技术,它研究的是因变量(目标)和自变量(特征)之间的关系。这种关系可以表示为一个线性方程,其中因变量是自变量的线性组合。
36 2
|
2月前
【数据结构OJ题】相交链表
力扣题目——相交链表
23 1
【数据结构OJ题】相交链表
|
1月前
|
算法
突击面试:解密面试官的算法题集合
突击面试:解密面试官的算法题集合
|
2月前
|
存储 算法 索引
算法与数据结构
算法与数据结构
33 8
|
20天前
|
算法
【初阶数据结构篇】二叉树算法题
二叉树是否对称,即左右子树是否对称.
|
20天前
|
算法 索引
【初阶数据结构篇】单链表算法题进阶
深拷贝应该正好由 n 个全新节点组成,其中每个新节点的值都设为其对应的原节点的值。
下一篇
DDNS