并查集之数组

本文介绍了并查集这一数据结构,用于解决动态连通性问题。通过初始化数组,每个元素表示一个节点及其所属组号,提供了查询节点组号、判断节点是否连通、连接节点以及获取组数的方法。并查集适用于追踪节点间的连通关系变化,但效率较低,时间复杂度为O(M*N),其中M为添加路径关系的数量,N为节点数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.ibm.unionfind;

/**
 * 并查集,也是一种常用的数据结构。主要用于解决动态连通性问题。
 * 给出孤立的多个节点集合,比如1到n,然后再给出数据对表示增加连接关系,比如3和5连接,
 * 那么随着输入数据对的不断增多,整个 集合的连通关系不断发生变化。
 * 并查集这种数据结构,就是用来追踪和描述这种连通关系变化的有效手段。
 * 
 * 初始化完毕之后,对该动态连通图有几种可能的操作:
 * 
 * 1 查询节点属于的组
 * 数组对应位置的值即为组号
 * 
 * 2 判断两个节点是否属于同一个组
 * 分别得到两个节点的组号,然后判断组号是否相等
 * 
 * 3 连接两个节点,使之属于同一个组
 * 分别得到两个节点的组号,组号相同时操作结束,不同时,将其中的一个节点的组号换成另一个节点的组号
 * 
 * 4 获取组的数目
 * 初始化为节点的数目,然后每次成功连接两个节点之后,递减1
 * 
 * 本算法实现简单,效率低,如果要添加的新路径关系的数量是M,节点数量是N,
 * 那么最后的时间复杂度就是O(M*N)
 * 
 *
 */
public class Union {
	
	private int[] a;
	private int groups;

	/**
	 * 数组元素下标表示不同的节点,节点标识符从0开始,如果是字符串,需要先映射成整数,
	 * 元素的值表示该节点所属的组,也是从0开始。
	 * @param n
	 */
	public void init(int n){
		assert(n>0);
		a = new int[n];
		for(int i=0; i<n; i++){
			a[i] = i;
		}
		groups = n;
	}
	
	/**
	 * 返回节点p的所属的组。
	 * @param p
	 * @return
	 */
	public int find(int p){
		assert(p>=0 && p<a.length);
		return a[p];
	}
	
	/**
	 * 判断两个节点是否连通。
	 * @param p1
	 * @param p2
	 * @return
	 */
	public boolean isConnected(int p1, int p2){
		assert(p1 != p2);
		assert(p1>=0 && p1<a.length);
		assert(p2>=0 && p2<a.length);
		return a[p1]==a[p2] ? true : false;
	}
	
	/**
	 * 合并节点p1和p2,为同一个组。
	 * 将p2所属组下面所有的节点都要更新成p1所属的组。
	 * @param p1
	 * @param p2
	 */
	public void union(int p1, int p2){
		if(!isConnected(p1, p2)){
			for(int i=0; i<a.length; i++){
				if(a[i] == a[p2]){
					a[i] = a[p1];
					groups--;
				}
			}
		}
	}
	
	public int getGroupCount(){
		return groups;
	}
	

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值