动态连通性 java_dynamic-connectivity动态连通性问题之quick-union算法

479fe5cbe2bdb225e90b451b01078ed2.png

quick-union 的思想是:若对象 p 的 root_id 和对象 q 的 root_id 相等,则认为 p 和 q 连通。

若要将对象 p 和对象 q 连通(已知两对象未连通),则将 p 的 root_id 的值设为 q 的 root_id 的值,这样 p 和 q 各自所在的两个树状结构将会合并

算法类源码:

public class QuickUnionUF {

private int[] id;

//访问id[] N 次

public QuickUnionUF(int size) {

id = new int[size];

for (int i = 0; i < size; i++) { //初始化id[]

id[i] = i;

}

}

//最多访问id[] N 次最少访问 1 次

private int root(int i) { //追寻父节点

while (i != id[i]) {

i = id[i];

}

return i;

}

//最多访问id[] N + N - 1 = 2N - 1 次,最少访问 1 + 1 = 2 次

//在最少的情况下,若只访问id[] 2 次,两个对象一定不是连通的

public boolean connected(int p, int q) {

return root(p) == root(q);

}

//若p,q从未连通

//则最多访问id[] N 次,最少访问 2 次

public void union(int p, int q) {

int i = root(p); // (N - 1) ~ 1

int j = root(q); // 1 ~ (N - 1)

id[i] = j;

}

public String toString() {

String temp = "{";

for (int i = 0; i < id.length; i++) {

if (i == id.length - 1) {

temp += id[i] + "}";

break;

}

temp += id[i] + ", ";

}

return temp;

}

}

测试类源码:

public class TestQuickUnion {

public static void main(String[] args) {

QuickUnionUF qu = new QuickUnionUF(10); //访问数组id[] 10 次

qu.union(4, 3);

System.out.println(qu); //{0, 1, 2, 3, 3, 5, 6, 7, 8, 9}

qu.union(3, 8);

System.out.println(qu); //{0, 1, 2, 8, 3, 5, 6, 7, 8, 9}

qu.union(6, 5);

System.out.println(qu); //{0, 1, 2, 8, 3, 5, 5, 7, 8, 9}

//连通 N 个对象需要访问id[] (N - 1) * 2 ~ (N - 1) * N 次

//访问id[]的次数随已连通对象的数目增加而增加

//最多增量为已连通对象的数目

//目前的这个算法的union()的时间复杂度有所改进

//但跟quick-find相比,它的connected()时间代价较大

System.out.println(qu.connected(8, 4)); //true

System.out.println(qu.connected(5, 4)); //false

}

}

4894ad99b125932e5bb64512eb0ce93f.png

quick-union 和 quick-find 同样慢(处理大量数据时花费的时间)。

quick-find 的缺点:

1、union() 的时间代价太大(访问 N 次数组)

2、多个对象连通后形成的树状结构是平展的,但是当需要连通的对象的个数 N 较大时,宏观上看,这种平展的树状结构的延伸,总体时间代价巨大!

quick-union 的缺点:

1、宏观上看,多个对象连通后形成的树状结构可能将变得非常高大;

2、find(connected())的时间代价很大(访问 2 ~ 2N -1 次数组)

文章来源: www.oschina.net,作者:Phpythoner_Alei,版权归原作者所有,如需转载,请联系作者。

原文链接:https://my.oschina.net/u/3637389/blog/3159658

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值