1.3:Union-Find算法-----quick-union算法的改进(加权的quick-union算法)

本文深入探讨了快速并查集算法的局限性,特别是其在处理分量不平衡时的最坏情况表现。通过引入加权机制,作者提出了一种改进策略,旨在通过在连接节点前判断树的大小并调整连接方向,从而有效预防树高度的不必要增长,显著降低查找操作的时间复杂度。

对于一般情况而言,使用quick-union算法就已经足够满足需求。但是仍然存在着一种情况使得quick-union算法得到的最快的情况。

quick-union的最坏情况:

当我们要对两个节点进行union操作时,等价于对两个节点所在的分量进行union操作(对于分量,用“树”这个词来表示更为妥当。因为一个节点总是指向它的“父节点”)。此时union(p, q)即将前者(p)的根节点指向后者(q)的根节点。若此时p所在的树的大小(即p所在分量节点的个数) 远大于 q所在树的大小。则经过若干次这样的操作后,树将会变得及其不平衡。这带来的直接后果是树的高度将接近所有分量的节点数目。这样一来,查找花费的代价将及其昂贵。如下图:

对于最坏情况的解决方案:

为了防止避免这种最坏情况的发生,一种解决方法是在连接两个节点(即连接两颗树时)进行判断,那棵树的节点多,然后将比较小的树连接到较大的一棵树上面。

可以看出,在连接前判断树的大小并将小树连接到大树的方法明显使得树更加平衡。这种方法叫做加权的quick-union算法。

代码如下:

public class WeightedQuickUnionUF {
	private int[] id;	//节点数组
	private int[] sz;	//用来保存各个根节点对应的分量大小
	private int count;	//连通分量的数量
	
	public WeightedQuickUnionUF(int N) {
		count = N;
		
		id = new int[N];
		for(int i = 0; i < N; i++)
			id[i] = i;
		
		sz = new int[N];
		for(int i = 0; i < N; i++)
			sz[i] = 1;
	}
	
	public int count() {
		return count;
	}
	
	public boolean connected(int p, int q) {
		return find(p) == find(q);
	}
	
	public int find(int p) {		
		while(p != id[p]) p = id[p];
		return p;
	}
	
	public void union(int p, int q) {
		int i = find(p);
		int j = find(q);
		if(i == j)	return;
		
		if(sz[i] < sz[j])	{id[i] = j; sz[j] += sz[i];}  
		else			{id[j] = i; sz[i] += sz[j];}
		
		count--;
	}	
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值