判定图中是否存在给定顶点v0的环

判定图中是否存在经过给定顶点 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;如果是就认为是双向边,过滤即可

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

燕南路GISer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值