1)查找网络中从一个特定节点s通过有向路径能够到达的所有节点;
2)查找网络中通过有向路径能够到达一个特定节点t的所有节点;
3)识别网络中所有的连接;
4)判断一个给定网络是不是二部图。
我们会在本节中讨论前两个问题。搜索算法还有另外一个重要应用——识别网络中的有向循环,如果是非环网络(acyclic),要对节点重新进行拓扑排序(topological ordering),使得对每个弧(i,j)∈A,i<j。
1. 问题一的解决方法——正向搜索算法(forward search algorithm)
我们首先考虑一个问题:在图G=(N,A)中,找到从源节点(source)出发能够到达的所有节点。网络中的节点有两种状态:已标记(marked)和未标记(unmarked)。已标记代表从源节点出发可以到达的节点;未标记代表尚未进行判断。如果节点i是已标记的,且存在弧(i,j),则节点j也可以标记。当网络中不存在可标记的节点时,搜索结束,算法终止。
搜索算法以一定的顺序遍历已标记的节点。LIST代表尚未检查的已标记节点集,因为这些节点可能会产生可接受(admissible)的弧,从而产生新的可标记节点。当搜索结束时,定义了一个由已标记节点构成的搜索树(search tree)。搜索算法如图1所示。
图1 搜索算法
如图2所示是两种搜索算法:广度优先搜索(breadth-first search)和深度优先(depth-first search)搜索。如果我们把LIST看作一个队列(先入先出),搜索树如图(b)所示,称为广度优先搜索,从源节点s到任意节点i的路径都是最短路径;如果我们把LIST看作一个队列(先入先出),搜索树如图(c)所示,称为深度优先搜索,任何节点的后代都按照顺序连续排序。
图2 两种搜索树
2. 问题二的解决方法——反向搜索算法(reverse search algorithm)
只需在1所述的方法中作3点微小改动:
1)初始化LIST={t}而不是LIST={s};
2)检查节点时,扫描其输入弧而不是输出弧;
3)设定可接受(admissible)弧的标准是(i,j)中i是未标记的(unmarked),而j是已标记的(marked),而不是相反。
我们可以对同一个网络同时进行正向搜索算法和反向搜索算法来判断它是否是强连通的(strong connectivity)(关于强连通的概念请见2.2节)。
3. 非环网络节点的拓扑排序问题(topological ordering)
图3 拓扑排序
如图3所示,演示了拓扑排序的含义。对于(a)所示的网络,存在诸如(5,4),(5,3),(4,3)等弧(i,j),使得i>j。而拓扑排序的目的则是通过重新排序节点标号,使得所有的弧(i,j)均满足i<j。因此,(b)不是一个拓扑排序(存在(4,3)),(c)、(d)均是拓扑排序。同一个网络可能有多个拓扑排序,有的网络没有拓扑排序。
可以证明:一个网络是无环网络当且仅当此网络有拓扑排序。
可以使用搜索算法很容易地实现拓扑排序。首先,选择任意一个入度为0的节点,标号为1,然后去掉它和从它出发的所有弧;之后再选择任意一个入度为0的节点,标号为2,然后去掉它和从它出发的所有弧;以此类推。如果最终网络仍然包含一些节点和弧,此网络是有环的。
如图4所示是拓扑排序算法。将所有入度为0的节点填入LIST列表,并且进行上述操作。
图4 拓扑排序算法