自定义并查集

一种特殊的多叉树。

主要支持两个方法:①union(p,q)  ②isConnected(p,q)

 

 

find方法中的路径压缩:

 

自定义并查集

 

 

基于rank的优化:

 

 

          以 union(4,2)为例: 将层数最少的元素2的根节点,指向层数较多的元素4的根节点。

                            首先是这样的

自定义并查集

                                                最终结果为

自定义并查集

 

 

 

并查集的时间复杂度为:O(h)   h代表树的深度:

 

自定义并查集

  总之 ,其时间复杂度近乎为O(1).

 

 

包结构:

自定义并查集

 

UF.java接口:

package UnionFind;

public interface UF {
	//并查集中元素的个数
	int getSize();
	//判断元素p和元素q是否属于同一集合
	boolean isConnected(int p,int q);
	//合并元素p所在的集合与元素q所在的集合
	void unionElements(int p,int q);
}

 

UnionFind.java:

package UnionFind;

public class UnionFind implements UF{
	//rank[i]表示以i为根的集合所表示的树的层数
    // 只是作为比较的一个标准,并没有不断维护。所以rank的值在路径压缩的过程中, 有可能不再是树的层数值
	private int[] rank;
	
	private int[] parent;// parent[i]表示第i个元素所指向的父节点
	/**
	 * 构造函数
	 * @param size
	 */
	public UnionFind(int size) {
		parent=new int[size];
		rank=new int[size];
		//初始化, 每一个parent[i]指向自己, 表示每一个元素自己自成一个集合
		for(int i=0;i<size;i++) {
			parent[i]=i;
			rank[i]=1;
		}
	}
		
	/**
	 * 并查集中元素的个数
	 */
	@Override
	public int getSize() {
		
		return parent.length;
	}
	
	/**
	 * 辅助方法
	 * 查找过程, 查找元素p所对应的集合编号
	 * @param p
	 * @return
	 */
	private int find(int p) {
		if(p < 0 || p >= parent.length)
            throw new IllegalArgumentException("索引越界");

        // 不断去查询自己的父亲节点, 直到到达根节点
        // 路径压缩,递归算法
        while(p != parent[p])
            parent[p]=find(parent[p]);
        return parent[p];
	}
	/**
	 * 判断元素p和元素q是否属于同一集合
	 */
	@Override
	public boolean isConnected(int p, int q) {
		
		return find(p)==find(q);
	}
	/**
	 * 合并元素p所在的集合与元素q所在的集合
	 */
	@Override
	public void unionElements(int p, int q) {
		 int pRoot = find(p);
	        int qRoot = find(q);

	        if( pRoot == qRoot )
	            return;

	        // 根据两个元素所在树的rank不同判断合并方向
	        // 将rank低的集合合并到rank高的集合上
	        if( rank[pRoot] < rank[qRoot] )
	            parent[pRoot] = qRoot;
	        else if( rank[qRoot] < rank[pRoot])
	            parent[qRoot] = pRoot;
	        else{ // rank[pRoot] == rank[qRoot]
	            parent[pRoot] = qRoot;
	            rank[qRoot] += 1;   // 维护rank的值
	        }
		
	}
	

}