判定图中是否存在经过给定顶点 v 0 v_{0} v0 的环
我的思路:以 v 0 v_{0} v0 为起点深度优先遍历 v 0 v_{0} v0 的每个邻接点,若回到 v 0 v_{0} v0 则有回路。
int isCircle=0;
int visited[Maxsize];//visited[]已经初始化为0;
void DFS(Graph *G,int v)
{
visited[v]=1;
for(w=firstNeighbor(G,v),w>=0,w=nextNeighbor(G,v,w))
{
if(w==v)//v必须全局变量才行。
{
isCiecle=1;
break;//此时w=v
}
if(visited[w]==0)
DFS(G,w);//break后在此处继续
}
}
void FindCircle()
{
DFS(G,v0);
if(isCircle==0)
cout<<"有回路"<<endl;
else
cout<<"没有回路"<<endl;
}
我做的问题:
1,判定函数,不应该是用输出来判定;应该是用返回值来判定。特别是递归函数如何驾驭好返回值?
2,过v0的环路不一定在v0上
3,break错误,结束后上层循环仍然继续。
4,v局部变量,不能用“w == v”判定,每次递归v都变
5,我这里还是两个函数拼凑着解决了问题,有没有办法使用一个函数解决。
解决方法:
1,专门多设置一个v1,改为w ==v1
void DFS(Graph *G,int v,int v1)
2,添加条件isCircle=1,第一次break后,isCircle=1就会结束循环
if(w ==v||isCircle=1)
与之前的不同:
之前一题也是判定回路,但是是判定整个图中是否有回路,因此要多一个数组记录每一次的情况。而这题只判定vo出发的情况,因此只需要通过visited数组来判定。
书上答案
递归函数中设一个局部变量flag,从v开始深度遍历,如果当前节点之前已被访问过,就是回路。没有访问过就继续递归。
bool DFS(AGraph *G,int v,bool visited[])
{
bool flag;
ArcNode *p;
visited[v]=true;
for(p=G->adjList[v].first;p!=NULL;p=p->next)
{
if(visited[p->adjV]==true)
return true;//本次递归找到环路
else
flag=DFS(G,p-adjvex,visited[]);
if(flag==true)
return true;//之前的递归找到环路
visited[p->adjvex]=0;//避免误判
}
return false;
}
//调用函数
isCircle = DFS(*G,v,visited);
如果两个节点都指向同一个节点,形成了环,但是没有连通。那么深度优先遍历会误判。因此要每次结束递归清除痕迹。
如果只判断,vo处有无回路呢?
1,visited[p->adjvex]=0;//删除,无需每次都初始化
2,双变量,从v开始遍历,如果再次访问到v就是在v处有环路
if(p->adjV==v)
return true;//本次递归找到环路
无向图双边如何过滤掉
认为a->b->a不是环
访问a的时候给a编号i,给a的孩子节点编号i+1;
在访问的时候来到一个新节点,且其孩子节点以及被访问
判断新节点编号是否等于其孩子节点编号+1;如果是就认为是双向边,过滤即可