(1小时数据结构)数据结构c++描述(二十六)--- 图(判断图是否有环)

有关图的定义,与代码程序的定义在上个章节中:传送们,图的定义与遍历

依旧是这个图,我们可以看到图是有环的。 

        那代码中我们如何去判断是否有环呢?图的环跟点链表是不同的,不能采用“时钟法”  来判断.那我们用什么办法呢,其实很简单,原理就是DFS遍历思想,在遍历的时候记录visited ,每个节点是false,遍历到了该成true ,遍历到下个节点是true就表明是环,但是如上图,当遍历1 2 5 8 的时候都为true, 但是当遍历1 3 5的时候5是true了,但是 这个不是有向有环图,于是我们加入onStack 来记录从顶点到终点的值(是否为true)。比如我们遍历 1 2 5 8的时候,遍历完了,有回到1点的时候把onStack全变false。于是我们遍历 1 3 5遇到5了,发现5在visited 中是true,表示5刚才遍历过了,但是onStack中是false 表明不是当前遍历的,可以知道,图中不是环。于是采用这个方法就可以遍历出图是不是有环的了,有环的情况就是 visited 为 true, onStack同时也true。

有关DFS遍历是上一章的知识点,不知道的同学们请看前一章。 

程序部分:

//判断是否有环
template<typename T>
 bool Graph<T>::HasCycle()
 {
	 bool *visited = new bool[n];
	 bool *onStack = new bool[n];    //由顶点索引的数组,以标记递归调用栈上的所有顶点
	 int *edgeTo = new int[n];       //edgeTo[i]存放指向i的边的点
	 ClearCycle();   

	 for (int i = 0; i < n; ++i) {
		 visited[i] = false;
		 onStack[i] = false;
		 edgeTo[i] = -1;
	 }

	 for (int j = 0; j < n; ++j) {
		 if (!visited[j]) {
			 DFSForCycle(j, visited, onStack, edgeTo);
		 }
	 }
	 delete[] visited;
	 delete[] onStack;
	 delete[] edgeTo;
	 if (hasCycle) {
		 return true;
	 }
	 else {
		 return false;
	 }

}

 ClearCycle()

//清空栈cycle中的记录
template<typename T>
void Graph<T>::ClearCycle()
{
	while (!cycle.empty())
	{
		cycle.pop(); //有的话就去掉
	}
}

DFSForCycle()

template<typename T>
void Graph<T>::DFSForCycle(int v, bool * visited, bool * onStack, int * edgeTo)
{
	onStack[v] = true;
	visited[v] = true;

	for (ENode<T> *w = enodes[v]; w; w = w->next) {
		if (hasCycle) {
			return;
		}
		else if (!visited[w->adjVex]) {
			edgeTo[w->adjVex] = v;
			DFSForCycle(w->adjVex, visited, onStack, edgeTo);
		}
		else if (onStack[w->adjVex]) {    //此顶点已经在递归调用的栈上,再次访问说明出现环了
										  //用栈cycle将环上的点都保存起来
			for (int i = v; i != w->adjVex; i = edgeTo[i]) {
				cycle.push(i);
			}
			cycle.push(w->adjVex);
			cycle.push(v);
			hasCycle = true;
		}
	}
	onStack[v] = false;     //消除在此递归调用栈上的记录,因为已经递归结束了
}

上面的代码是查找是否有环,并把他们环放到栈中,然后采用出栈的方式来获取环状的环数据。

 //返回环
template<typename T>
stack<int> Graph<T>::GetCycle()
{
	stack<int> tmp(cycle);
	return tmp;
}

判断图中有没有环,其主要思想就是利用DFS遍历的思想,当下个节点是之前遍历过的数据,说明有环。 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值