之前写了图的基本概念,现在写图的一般应用。
一.寻找一条路径
用广度优先搜索,虽然能很好的找到能到达的所有点,但是却不容易找到路径,而深度优先搜索里面隐含了路径,所以寻找路径一般用深度优先搜索。
bool rFindPath(int s)
{//寻找路径的实际算法。从顶点s开始实施深度优先搜索
//顶点s不应该等于终点
//当且仅当一条路径找到了,返回true
reach[s]=1;//标记起始点
vertexIterator<T>* is=iterator(s);//以s为起点的迭代器
int u;
while((u=is->next())!=0)//当s存在邻接点时
{//访问s的一个邻接顶点
if(reach[u]==0)//u是一个没有到达的顶点
{//移到顶点u
path[++length]=u;//不管对不对先加入到路径中,不对再删除
if(u==destination||rFindPath(u))
return true;
//从顶点u到终点没有路径
length--;//从路径中删除u
}
}
delete is;
return false;
}
这是一个迭代算法,使用了深度优先搜索的方法,定义一条路径数组,我们将算法寻找的点全部点插入路径数组,如果最后一个点是目标点则结束算法,不然上退一格删除上一个插入的点,然后从上退的那个点开始重新寻找路径。
int *findPath(int theSource,int theDestination)
{
int n=numberOfVertices();
path=new int[n+1];
path[1]=theSource;//第一个顶点总是
length=1;//当前路径长度+1
destination=theDestination;
reach=new int [n+1];
for(int i=1;i<=n;i++)
reach[i]=0;
if(theSource==theDestination||rFindPath(theSource))
//找到一条路径
path[0]=length-1;//index 0里面存取路径长度
else
{
delete [] path;
path=NULL;
}
delete [] reach;
return path;
}
上述代码为寻找路径的前序代码,主要作用是定义变量数组和调用rfindPath函数。代码只是能寻找到一条路径但不保证是最短路径。
二.检查一个图是否是连通的
以下代码确定一个无向图是否连通。
bool connected()
{//当且仅当图连通时,返回true
//确定这是一个无向图
if(directed())
throw undefinedMethod("graph::connected() not defined for directed graphs");
int n=numberOfVertices();
reach=new int [n+1];//默认reach[i]=0
dfs(1,reach,1);
//检查是否所有顶点都已经标记
for(int i=1;i<=n;i++)
if(reach[i]==0)
return false;
return true;
}
原理很简单,就是判断起始点与任意其他点之间是否有一条路径。
以下代码解决构建标记问题(就是确定一个图有一个连通区域)
int labelComponents(int c[])
{
//给无向图的构建做标记
//返回构建的个数
//令c[i]是顶点i的构件号
//确定是一个无向图
if(directed())
throw undefinedMethod("graph::connected() not defined for directed graphs");
int n=numberOfVertices();
//令所有顶点是非构件
for(int i=1;i<=n;i++)
c[i]=0;
label=0;//初始化标记为0
for(int i=1;i<=n;i++)
if(c[i]==0)//顶点i未到达
{//顶点i是一个新构件
label++;
bfs(i,c,label);//给新构件做标记
}
return label;
}