健指算法(二)模拟网络连通检查(按秩归并&路径压缩)

本文介绍了如何使用按秩归并和路径压缩优化并查集算法,以高效解决模拟网络连通检查问题。通过树结构表示网络结点,通过查找根结点判断结点间是否连通,并通过按秩归并策略减少树的高度,路径压缩则进一步加速查找操作。详细解释了这两种优化方法的实现过程,并提供了完整代码链接。
摘要由CSDN通过智能技术生成

本来打算写多线程ThreadLocal的源码的,为什么突然转来写一篇关于并查集的日志,因为最近在改自己以前写的代码时,发现很多地方可以改写得更好,对于我来说,平时除了开发自己喜欢的软件外,最大的乐趣就是优化以前写过的代码,这次就来总结下当初写的并查集的两种优化算法:按秩归并和路径压缩。

例子是模拟网络连通检查,是这样一个问题,假设网络中分布着各个结点,这些结点可以是主机或是路由器,它们之间有的可以互相通信,有的还没有建立连接,无法通信。我们要写出一个程序,输入两个结点信息,判断它们是否能够通信,如果可以,则输出提示,否则让它们之间建立连接。因为是网络上的结点,它们有传递特性,即如果结点A和结点B连接,结点B和结点C连接,那么结点A和结点C也就建立了连接。如果结点A和结点B连接后,这对结点合并成一个连通分量,当结点B和结点C连接后,结点ABC三个也合并成了一个连通分量。

      这些结点的存储结构用树来表示,那么这个网络就是一片森林。为什么要用树来存储这些结点,因为我们来看看互连网络:

一个路由器可连接多个交换机,一个交换机能连接多台主机,所以用树来作为存储结构能很形象地表示出网络。树结点保存着与该结点相连的另外一个结点的名称,用这种关系来表示它们的连接状态,这样我们就可以从一个结点得到与其相连的下一个结点,由此我们可以一直寻找某一个连通分量中所含有的结点,直到最后找到根结点,即结点中标识符等于自己的结点,我们可以利用连通分量的根结点来判断两个结点是否相连,如果两个结点已连接,那么它们的根结点一定是相同的。接下来,根据问题的解决过程来设计API:

  1. 第一步查找两个结点所在的连通分量,如果两个结点处在同一个连通分量中,那么它们就是已连接的:初始时假设这个网络中所有结点都是互不相连的,各自都是一个连通分量,当两个结点的父结点相同时,就认为它们是相连的网络,处在同一个连通分量中:
//查找网络n所在的连通分量标识符(用其根结点标识这个网络)
	public int Search(int networkAddress) {
		while(networkAddress != networkID[networkAddress]) {
			networkAddress = networkID[networkAddress]; //往上寻找它的根结点
		}
		return networkID[networkAddress];
	}

Search方法就是用来寻找一个结点的根结点,初始时所有结点都未相连,所以结点标识符都是等于自己,当两个结点例如A和B连接后,B结点的标识符就等于A了,所以可以从networkAddress[ B ] = A得到B与A连接,再从networkAddress[ A ] = A得到结点A是根结点,A就是这个连通分量的标识符,当结点C与结点B连接后,networkAddress[ C ] = B,由此可得C与B连接,再从networkAddress[ B ] = A找到A结点,所以结点C的根结点也是A,所以,结点ABC都拥有共同的根结点A,即表示这三个结点已建立连接。

  1. 判断两个结点(或连通分量也行,有可能是一个连通分量中有多个结点,另一个连通分量中只有初始的一个结点)的连接状态:
//判断两个网络分量的连接状态
	public boolean ConnectionState(int networkAddress1, int networkAddress2) {
		return (Search(networkAddress1) == Search(networkAddress2));
	}

就是调用Search()方法查找两个结点所在连通分量的根结点(标识符),判断它们是否相等,作为是否要将它们连接的依据。

  1. 如果两个连通分量未连接,则为它们建立连接:建立连接前先获得两个连通分量的标识符,判断不相等后便把其中一个连通分量链接到另一个连通分量上,最后把记录网络中连通分量的变量componentCount--。

来看下运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值