您的位置:首页 > 理论基础 > 数据结构算法

数据结构研究之借连通性问题看算法设计

2011-05-22 18:06 645 查看
今天我们来看一个比较经典的例子,连通性问题(Connectivity)。通过对这个问题的求解,我们来看看对于一个实际问题在设计算法时候的处理思路。

一:连通性问题。


假如已知一个整数对(pair),每个整数代表某个类型的一个对象,而且将P-Q对解释为P和Q连通,假设连通关系具有传递性。


我们的问题有以下几个:

如果我们属于一个整数对p-q,但是此时p-q已经是连通的,那么这个数据就是冗余的,我们需要剔除这个冗余数据。

二:问题分析

其实对于上面的问题最核心的是如何让程序记住已经获得的连通信息,随时可以检索任意两个数字是否连通。这个问题很有实际意义。

比如说:整数可以代表一个网络中的计算机,对代表可以连通的计算机对。我们就可以判断在计算机p-q之间是否连接。在这种情况下我们可能要处理的点有很多,几万,几百万,甚至上亿。所以需要有一个好的算法。下面给出一个截图,如何判断在下面这个网络中,两个点是否连通。

加权连接树

public void AddPair(int p, int q)
{
if (p < 0 || p > N || q < 0 || q > N)
{
Console.WriteLine("input error!p={0},q={1}.", p, q);
}
//找到P的顶节点
for (; id[p] != p; p = id[p])
//找到Q的顶节点
for (; id[q] != q; q = id[q])
//如果两个节点不连通
if (p!=q)
{//设置连通
if (size[p]<size[q])
{
id[p] = q;
size[q] += size[p];
}
else
{
id[q] = p;
size[p] += size[q];
}
}
}


{
if (p < 0 || p > N || q < 0 || q > N)
{
Console.WriteLine("input error!p={0},q={1}.", p, q);
}
//找到P的顶节点
for (; id[p] != p; p = id[p])
//找到Q的顶节点
for (; id[q] != q; q = id[q])
//如果两个节点不连通
if (p!=q)
{//设置连通
if (size[p]<size[q])
{
id[p] = q;
size[q] += size[p];
}
else
{
id[q] = p;
size[p] += size[q];
}
}
}
[/code]

加权连接的方式最坏的情况是,每次两个树进行连接的时候,树的大小都是相同的。如果对象的个数小于2^n个,那么从节点到顶节点的最大距离就是n-1.
这样大大提高了我们连通树中查找某个节点顶节点的效率。

4:当然对于我们的应用程序来说,我们最希望的结果是每个节点都指向新的根,这样我们的搜索效率会大大提高。虽然我们不可能做到每个节点都指向根,但是我们有一些简单有效的方法来压缩整个树,使树的高度大大减小。比如说如果一个树中的结构超过了3层,我们就可以压缩一下:

1--》2---》3可以压缩成1---》3《----2.

我们在遍历一个树找顶节点的同时,可以将当前树压缩一下:

public void AddPair(int p, int q)
{
if (p < 0 || p > N || q < 0 || q > N)
{
Console.WriteLine("input error!p={0},q={1}.", p, q);
}
//找到P的顶节点
for (; id[p] != p; p = id[p])
{//让当前节点指向他父节点的父节点,压缩树
id[p] = id[id[p]];
}
//找到Q的顶节点
for (; id[q] != q; q = id[q])
{//让当前节点指向他父节点的父节点,压缩树
id[1] = id[id[q]];
}
//如果两个节点不连通
if (p!=q)
{//设置连通
if (size[p]<size[q])
{
id[p] = q;
size[q] += size[p];
}
else
{
id[q] = p;
size[p] += size[q];
}
}
}

下面我们看一个例子:





对于我们寻找8的顶节点的时候同时进行压缩,等找到顶节点后,树的结构也由上面的形式变成了下面的格式。

这样大大的减少了任意一个节点到顶节点的距离,在寻找的时候遍历的次数大大减少。

现在这个算法已经是一个比较优良的算法,兼顾了并集时的运行速度以及查找时候的运行速度,所以说这个算法已经基本可以满足我们的实际问题的解决。

六:总结

回过头看我们这个问题解决过程中,对于算法的一步一步的改进,每一步的改进都是对算法的优化,总结一下我们算法设计的过程。

我们开发的过程是这样的:

1:确定问题的本质,确定基本的抽象运算。

2:对简单算法先仔细的开发出一个实现。

3:通过逐级的细化,以便能够得到优化,通过实验分析或者数学分析来验证和改进构思。

4:找出算法中高级的抽象表示,或者具有改进版本的核心改动的算法。

5:在可能的情况下,尽量争取最坏情况的性能保证,但是同时呢还要保证普通情况下的性能。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐