【算法笔记】并查集

并查集

并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的合并及查询问题。

并查集实现,我终于看懂了的博客 o(╥﹏╥)o

package leetcode;

/**
 * 并查集
 * 并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的合并及查询问题。
 * 以下实现是,考虑rank树高的
 */
public class UnionFind{
	private int[] parent;//父亲结点
	private int[] weight;//重量,集合中node的数量
	private int size;

	public UnionFind(int size){
		this.parent = new int[size+1];
		this.weight = new int[size+1];
		this.size = size;
		for (int i = 0; i < size; i++){
			this.parent[i] = i;
			this.weight[i] = 1;
		}
	}

	/**
	 * 查找find
	 * 路径压缩:让当前结点指向自己父亲的父亲,没有改变根结点的weight(非根节点的weight改变了无所谓)。
	 *
	 * 找寻节点的根节点
	 * @param node 节点
	 * @return 返回节点的根节点
	 */
	public int find(int node){
		while(node != parent[node]){
			parent[node] = parent[parent[node]];//路径压缩
			node = parent[node];
		}
		return node;
	}

	/**
	 * 还是有并查集深度太深的问题。并查集越深,就越接近线性,find函数就越接近O(n)
	 * 所以有了这种基于高度的union。合并时,选择将weight少的合并到weight多的集合中
	 *
	 * 合并两个节点
	 * @param node1 第一个结点
	 * @param node2 第二个结点
	 */
	public void union(int node1, int node2){
		int node1Root = find(node1);
		int node2Root = find(node2);
		if(node1Root == node2Root){
			return;
		}

		if (weight[node1Root] > weight[node2Root]){
			parent[node2Root] = node1Root;
			weight[node1Root] += weight[node2Root];
		}else{//weight[node1Root] <= weight[node2Root]
			parent[node1Root] = node2Root;
			weight[node2Root] += weight[node1Root];
		}
	}

	/**
	 * 判断两个节点是否属于同一个集合
	 * @param node1 第一个结点
	 * @param node2 第二个结点
	 * @return 如果是则返回true
	 */
	public boolean isConnected(int node1, int node2){
		return find(node1) == find(node2);
	}

	/**
	 * 打印,输出parent,weight数组,展示
	 */
	public void printArr(){
		for(int p : parent){
			System.out.print(p+"\t");
		}
		System.out.println();
	}

/*
	public static void main(String[] args){
		int n = 10;
		UnionFind union = new UnionFind(n);
		System.out.println("初始:");
		union.printArr();

		System.out.println("连接了5 6");
		union.union(5, 6);
		union.printArr();

		System.out.println("连接了1 2");
		union.union(1, 2);
		union.printArr();

		System.out.println("连接了2 3");
		union.union(2, 3);
		union.printArr();

		System.out.println("连接了1 4");
		union.union(1, 4);
		union.printArr();

		System.out.println("连接了1 5");
		union.union(1, 5);
		union.printArr();

		System.out.println("1  6 是否连接:" + union.isConnected(1, 6));

		System.out.println("1  8 是否连接:" + union.isConnected(1, 8));

		System.out.println("2  5 是否连接:" + union.isConnected(2, 5));

		System.out.println("2  5 是否连接:" + union.isConnected(6, 5));

		System.out.println("连接了8 5");
		union.union(8, 5);
		union.printArr();

		System.out.println("8  3 是否连接:" + union.isConnected(8, 3));
	}*/
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值