问题描述:
这个题目应该是,2011年某高校的考研题目,正好最近面试碰上,现在翻出来总结一下。
设计算法,采用图的遍历方法(广度优先或者深度优先)判断给定的连通图 G
是否存在回路(环),如何存在回路返回 true
,反正返回 false
。
假设Graph
为连通图G
的数据类型,其中下列基本操作可以在算法中直接使用:
FirstAdjVex(G, v)
// 返回连通图G
中的v
顶点的第一个邻接点,如果没有返回NULL
。NextAdjVex(G, v, w)
// 返回连通图G
中v
顶点(相对于w
)的下一个邻接点,如果没有返回NULL
。
该算法原型定义为:
bool existCyclePath(Graph, int v)
问题分析:
注意事项:
- 题目中,已经给出的图
G
是连通图,所以,可以少考虑一些情况。 - 题目中没有提及是无向图还是有向图,所以,要特别注意。
解决方法:
- 使用图的深度优先搜索,从一个点从发,深度搜索每一条路径。
- 对每次走过的路径顶点,进行标记,说明已经走过。
- 如果当前顶点,已经被标记走过了,则表示有回路,否则继续深度前行。
- 在回溯的过程中,要对当前顶点,重新标记,即,没走过。
代码实现:
const int VEX_MAX = 100; // 图中最大顶点数
int visited[VEX_MAX]; // 同一条遍历路径上顶点的访问标记
// 从顶点v 出发深度优先搜索图G,判断图中是否存在回路
bool existCyclePath(Graph G, int v){
// 访问顶点 v
visited[v] = 1; // 访问过标记
// 遍历 v 的邻接点
for(w=FirstAdjVex(G, v); w!=NULL; w=NextAdjVex(G, v, w)) {
if(visited[w]) return ture; // 如果w已经访问过,必存在回路,直接返回即可
if(existCyclePath(G, w)) return true; // 如果从w出发,发现回路,则返回(进入递归调用)
}
// 遍历完 v 的所有邻接点,未发现回路,从顶点v返回
visited[v] = 0; // 清除访问标记
return false; // 没发现回路
}
声明: 总结学习,有问题或不妥之处,可以批评指正哦。
题目链接:应该是北工大11年的考研题目。
参考链接:参考历年解析