@(文章目录)数组
对于并查集(不相交集合)
,不少人会感到很陌生
,没听过或者不是特别了解。实际上并查集是一种挺高效的数据结构。实现简单,只是全部元素统一听从一个规律
因此让办事情的效率高效起来。数据结构
对于定意义,百科上这么定义的:函数
并查集,在一些有N个元素的集合应用问题中,咱们一般是在开始时让每一个元素构成一个单元素的集合,而后按必定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪一个集合中。其特色是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,每每在空间上过大,计算机没法承受;即便在空间上勉强经过,运行的时间复杂度也极高,根本就不可能在比赛规定的运行时间(1~3秒)内计算出试题须要的结果,只能用并查集来描述。学习
并查集是一种树型的数据结构
,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。经常在使用中以森林来表示。this
各自为根
join(a,b)
操做。a,b两个集合
合并。注意这里的a,并非a,b合并,而是a,b的集合合并。这就派生了一些状况:data[a]=b
;同时为了表示这个集合有多少个,本来-1
的b再次-1.即data[b]=-2
.表示以b为父亲的节点有|-2|个。不能直接操做a,b
(由于a,b可能已经指向别人了.)那么咱们只能操做a,b的祖先。由于a,b的祖先是没有指向的(即数据为负值表示大小)。那么他们首先一个负值要加到另一个上面去。另外这个数值要变成指向的那个表示联系。对于上述你可能会有疑问:3d
节点根祖先的结果是否相同便可
。由于只有根的数值是负的,而其余都是正数表示指向的元素。因此只须要一直寻找直到不为正数进行比较便可
!因此咱们一般是:小数指向大树(或者低树指向高树),这个使得查询效率可以增长!
固然,在高度和数量的选择上,还须要你本身选择和考虑。code
每次查询,自下向上。当咱们调用递归的时候,能够顺便压缩路径,由于咱们查找一个元素其实只须要直到它的祖先,因此当他距离祖先近那么下次查询就很快
。而且压缩路径的代价并不大!
blog
并查集实现起来较为简单,直接贴代码!递归
package 并查集不想交集合; import java.util.Scanner; public class DisjointSet { static int tree[]=new int[100000];//假设有500个值 public DisjointSet() {set(this.tree);} public DisjointSet(int tree[]) { this.tree=tree; set(this.tree); } public void set(int a[])//初始化全部都是-1 有两个好处,这样他们指向-1说明是本身,第二,-1表明当前森林有-(-1)个 { int l=a.length; for(int i=0;i<l;i++) { a[i]=-1; } } public int search(int a)//返回头节点的数值 { if(tree[a]>0)//说明是子节点 { return tree[a]=search(tree[a]);//路径压缩 } else return a; } public int value(int a)//返回a所在树的大小(个数) { if(tree[a]>0) { return value(tree[a]); } else return -tree[a]; } public void union(int a,int b)//表示 a,b所在的树合并 { int a1=search(a);//a根 int b1=search(b);//b根 if(a1==b1) {System.out.println(a+"和"+b+"已经在一棵树上");} else { if(tree[a1]<tree[b1])//这个是负数,为了简单减小计算,不在调用value函数 { tree[a1]+=tree[b1];//个数相加 注意是负数相加 tree[b1]=a1; //b树成为a的子树,直接指向a; } else { tree[b1]+=tree[a1];//个数相加 注意是负数相加 tree[a1]=b1; //b树成为a的子树,直接指向a; } } } public static void main(String[] args) { DisjointSet d=new DisjointSet(); d.union(1,2); d.union(3,4); d.union(5,6); d.union(1,6); d.union(22,24); d.union(3,26); d.union(36,24); System.out.println(d.search(6)); //头 System.out.println(d.value(6)); //大小 System.out.println(d.search(22)); //头 System.out.println(d.value(22)); //大小 } }
并查集还普遍用于迷宫游戏
中,下面有机会能够介绍用并查集实现一个走迷宫小游戏。你们欢迎关注!笔者学习资源
也放置公众号和你们一块儿分享!