关于union-find中的quick-find,quick-union以及加权quick-union

在判断一个图是否联通的时候用union-find与quick-find算法来进行判断:
quick-find中的算法为:定义一个数组来存根节点的值,只要属于此类,就将在此类节点中的值都设为根节点,将其归为一类,当两类互相向连接的时候,则需要将其中的一个类的所有节点的的值都改为另外一类中的根节点。
具体实现:

private int[] id;
	private int count;
	public quick_find(int N) {
		count=N;
		id = new int[N];
		for(int i =0;i<N;i++)//初始值,每一个值为其本身
			id[i]=i;
	}
	public int count() {
		return count;//判断有几个类
	}
	public boolean connectend(int p,int q) {
		return find(p)==find(q);
	}
	public int find(int p) {
		return id[p];
	}
	public void union(int p,int q) {
		int pID=find(p);
		int qID=find(q);
		if(pID==qID) return;
		for(int i=0;i<id.length;i++)
			if(id[i]==pID)id[i]=qID;//每个节点对应他的根节点
		count--;
	}

利用主函数来调用函数内的union中的连接;

算法quick-union中的算法实现:
思想:在quick-find中每次调用union中都会遍历一遍数组,算法复杂度高。则quick-union则将每一个节点记住他的根节点,然后不断记录根节点。当两个类互相连接的时候,则将这个类中的一个节点的下一个节点记录为这个类中的节点;
代码实现:

package Algorithm;

import java.util.Scanner;

public class union_find {
/*
 * 实现union_find算法:
 * 体现:找寻两个点之间是否是联通
 * 思想:定义一个数组进行存储每个点的下一个点的值
 * 如:A[i]=j;为此点为i,,其下一个节点为j来进行联通表示
 * 首先要进行初始值,将其每一个值都定义为他们原来的值
 * 
 * 
 * */
	private int[] id;
	private int count;
	public union_find(int N) {
		count = N;//记录初始值的分量
		id = new int[N];
		for(int i =0;i<N;i++)
			id[i]=i;//赋值为原值
	}
	public int count() {
		return count;//返回长度
	}
	public boolean connected(int p,int q) {
		return find(p)==find(q);
	}
	public int find(int p) {
		while(id[p]!=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 ;
		id[q]=p;
		count--;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner=  new Scanner(System.in);
		int N = scanner.nextInt();
		union_find uf = new union_find(N);
		while(!scanner.hasNext()) {
			int p =scanner.nextInt();
			int q = scanner.nextInt();
			if(uf.connected(p, q))continue;
			uf.union(p, q);
			System.out.println(p+" "+q);
		}
		System.out.println(uf.count+" components");
				
	}

}

主函数有点错!!需要输入几组数据的时候请具体分析!

加权quick-uion在前两个基础上,由于不可以判断哪一个类的节点多,则耗时会很大,则我们可以定义一个函数来存储每一个类中的节点数目,则可以将小类归纳到大类中去,避免大类归纳到小类,具体代码:

public void union(int p,int q) {//进行判断是否进行创新新节点
		int i=find(p);//找寻其节点
		int j = find(q);
		if(i==j) return ;
		if(num[i]<num[j]) {//判断谁的子节点多,多的话则将其设为大树
				id[i]=j;//头节点指向j的头几点
				num[j]+=num[i];
		}
		else {
			id[j]=i;
			num[i]+=num[j];
		}
		count--;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值